copy from squiz common
This commit is contained in:
parent
2dd714b369
commit
18fe7fd62a
@ -5,10 +5,10 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"gitea.pena/SQuiz/answerer/clients"
|
"gitea.pena/SQuiz/answerer/clients"
|
||||||
|
"gitea.pena/SQuiz/answerer/dal"
|
||||||
|
"gitea.pena/SQuiz/answerer/healthchecks"
|
||||||
|
"gitea.pena/SQuiz/answerer/middleware"
|
||||||
"gitea.pena/SQuiz/answerer/service"
|
"gitea.pena/SQuiz/answerer/service"
|
||||||
"gitea.pena/SQuiz/common/dal"
|
|
||||||
"gitea.pena/SQuiz/common/healthchecks"
|
|
||||||
"gitea.pena/SQuiz/common/middleware"
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/skeris/appInit"
|
"github.com/skeris/appInit"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
@ -79,7 +79,7 @@ func New(ctx context.Context, opts interface{}, ver appInit.Version) (appInit.Co
|
|||||||
zap.String("SvcBuildTime", ver.BuildTime),
|
zap.String("SvcBuildTime", ver.BuildTime),
|
||||||
)
|
)
|
||||||
|
|
||||||
pgdal, err := dal.New(ctx, options.PostgresCredentials, nil)
|
pgdal, err := dal.New(ctx, options.PostgresCredentials)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
255
dal/dal.go
Normal file
255
dal/dal.go
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
package dal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
_ "embed"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"gitea.pena/SQuiz/answerer/dal/sqlcgen"
|
||||||
|
"gitea.pena/SQuiz/answerer/model"
|
||||||
|
_ "github.com/ClickHouse/clickhouse-go"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/lib/pq"
|
||||||
|
_ "github.com/lib/pq"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DAL struct {
|
||||||
|
pool *sql.DB
|
||||||
|
queries *sqlcgen.Queries
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(ctx context.Context, cred string) (*DAL, error) {
|
||||||
|
pool, err := sql.Open("postgres", cred)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
timeoutCtx, cancel := context.WithTimeout(ctx, time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
if err := pool.PingContext(timeoutCtx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
queries := sqlcgen.New(pool)
|
||||||
|
|
||||||
|
return &DAL{
|
||||||
|
pool: pool,
|
||||||
|
queries: queries,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DAL) Close(ctx context.Context) error {
|
||||||
|
err := d.pool.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DAL) GetQuizByQid(ctx context.Context, qid string) (model.Quiz, error) {
|
||||||
|
_, err := uuid.Parse(qid)
|
||||||
|
if err != nil {
|
||||||
|
return model.Quiz{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("QUID", `
|
||||||
|
SELECT * FROM quiz
|
||||||
|
WHERE
|
||||||
|
deleted = false AND
|
||||||
|
archived = false AND
|
||||||
|
status = 'start' AND
|
||||||
|
qid = $1;
|
||||||
|
`)
|
||||||
|
rows, err := d.pool.QueryContext(ctx, `
|
||||||
|
SELECT * FROM quiz
|
||||||
|
WHERE
|
||||||
|
deleted = false AND
|
||||||
|
archived = false AND
|
||||||
|
(status = 'start' OR status = 'ai') AND
|
||||||
|
qid = $1;
|
||||||
|
`, qid)
|
||||||
|
if err != nil {
|
||||||
|
return model.Quiz{}, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
if !rows.Next() {
|
||||||
|
return model.Quiz{}, rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
var piece model.Quiz
|
||||||
|
pIds := pq.Int32Array{}
|
||||||
|
if err := rows.Scan(
|
||||||
|
&piece.Id,
|
||||||
|
&piece.Qid,
|
||||||
|
&piece.AccountId,
|
||||||
|
&piece.Deleted,
|
||||||
|
&piece.Archived,
|
||||||
|
&piece.Fingerprinting,
|
||||||
|
&piece.Repeatable,
|
||||||
|
&piece.NotePrevented,
|
||||||
|
&piece.MailNotifications,
|
||||||
|
&piece.UniqueAnswers,
|
||||||
|
&piece.Super,
|
||||||
|
&piece.GroupId,
|
||||||
|
&piece.Name,
|
||||||
|
&piece.Description,
|
||||||
|
&piece.Config,
|
||||||
|
&piece.Status,
|
||||||
|
&piece.Limit,
|
||||||
|
&piece.DueTo,
|
||||||
|
&piece.TimeOfPassing,
|
||||||
|
&piece.Pausable,
|
||||||
|
&piece.Version,
|
||||||
|
&piece.VersionComment,
|
||||||
|
&pIds,
|
||||||
|
&piece.CreatedAt,
|
||||||
|
&piece.UpdatedAt,
|
||||||
|
&piece.QuestionsCount,
|
||||||
|
&piece.PassedCount,
|
||||||
|
&piece.AverageTime,
|
||||||
|
&piece.SessionCount,
|
||||||
|
&piece.GigaChat,
|
||||||
|
); err != nil {
|
||||||
|
return model.Quiz{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
piece.ParentIds = pIds
|
||||||
|
|
||||||
|
return piece, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DAL) GetQuestionListByIDs(ctx context.Context, ids []int32) ([]model.Question, error) {
|
||||||
|
rows, err := d.queries.GetQuestionListByIDs(ctx, ids)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var questions []model.Question
|
||||||
|
for _, row := range rows {
|
||||||
|
question := model.Question{
|
||||||
|
Id: uint64(row.ID),
|
||||||
|
QuizId: uint64(row.QuizID),
|
||||||
|
Title: row.Title,
|
||||||
|
Description: row.Description.String,
|
||||||
|
Type: string(row.Questiontype.([]byte)),
|
||||||
|
Required: row.Required.Bool,
|
||||||
|
Deleted: row.Deleted.Bool,
|
||||||
|
Page: int(row.Page.Int16),
|
||||||
|
Content: row.Content.String,
|
||||||
|
Version: int(row.Version.Int16),
|
||||||
|
ParentIds: row.ParentIds,
|
||||||
|
CreatedAt: row.CreatedAt.Time,
|
||||||
|
UpdatedAt: row.UpdatedAt.Time,
|
||||||
|
Auditory: row.Auditory,
|
||||||
|
}
|
||||||
|
|
||||||
|
questions = append(questions, question)
|
||||||
|
}
|
||||||
|
|
||||||
|
return questions, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DAL) CreateQuestion(ctx context.Context, record *model.Question) (uint64, error) {
|
||||||
|
params := sqlcgen.InsertQuestionParams{
|
||||||
|
QuizID: int64(record.QuizId),
|
||||||
|
Title: record.Title,
|
||||||
|
Description: sql.NullString{String: record.Description, Valid: true},
|
||||||
|
Questiontype: record.Type,
|
||||||
|
Required: sql.NullBool{Bool: record.Required, Valid: true},
|
||||||
|
Page: sql.NullInt16{Int16: int16(record.Page), Valid: true},
|
||||||
|
Content: sql.NullString{String: record.Content, Valid: true},
|
||||||
|
ParentIds: record.ParentIds,
|
||||||
|
UpdatedAt: sql.NullTime{Time: time.Now(), Valid: true},
|
||||||
|
Session: record.Session,
|
||||||
|
Auditory: record.Auditory,
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := d.queries.InsertQuestion(ctx, params)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
record.Id = uint64(data.ID)
|
||||||
|
record.CreatedAt = data.CreatedAt.Time
|
||||||
|
record.UpdatedAt = data.UpdatedAt.Time
|
||||||
|
|
||||||
|
return record.Id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DAL) CreateAnswers(ctx context.Context, answers []model.Answer, session, fp string, quizID uint64) ([]model.Answer, []error) {
|
||||||
|
var (
|
||||||
|
createdAnswers []model.Answer
|
||||||
|
errs []error
|
||||||
|
)
|
||||||
|
|
||||||
|
tx, err := d.pool.BeginTx(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, []error{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ans := range answers {
|
||||||
|
if ans.Utm == nil {
|
||||||
|
ans.Utm = make(model.UTMSavingMap)
|
||||||
|
}
|
||||||
|
utmJSON, err := json.Marshal(ans.Utm)
|
||||||
|
if err != nil {
|
||||||
|
return nil, []error{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
params := sqlcgen.InsertAnswersParams{
|
||||||
|
Content: sql.NullString{String: ans.Content, Valid: true},
|
||||||
|
QuizID: int64(quizID),
|
||||||
|
QuestionID: int64(ans.QuestionId),
|
||||||
|
Fingerprint: sql.NullString{String: fp, Valid: true},
|
||||||
|
Session: sql.NullString{String: session, Valid: true},
|
||||||
|
Result: sql.NullBool{Bool: ans.Result, Valid: true},
|
||||||
|
Email: ans.Email,
|
||||||
|
Device: ans.Device,
|
||||||
|
DeviceType: ans.DeviceType,
|
||||||
|
Ip: ans.IP,
|
||||||
|
Browser: ans.Browser,
|
||||||
|
Os: ans.OS,
|
||||||
|
Start: ans.Start,
|
||||||
|
Utm: utmJSON,
|
||||||
|
Version: ans.Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
row, err := d.queries.InsertAnswers(ctx, params)
|
||||||
|
createdAnswer := model.Answer{
|
||||||
|
Id: uint64(row.ID),
|
||||||
|
Content: row.Content.String,
|
||||||
|
QuizId: uint64(row.QuizID),
|
||||||
|
QuestionId: uint64(row.QuestionID),
|
||||||
|
Fingerprint: row.Fingerprint.String,
|
||||||
|
Session: row.Session.String,
|
||||||
|
Result: row.Result.Bool,
|
||||||
|
New: row.New.Bool,
|
||||||
|
Email: row.Email,
|
||||||
|
DeviceType: row.DeviceType,
|
||||||
|
Device: row.Device,
|
||||||
|
OS: row.Os,
|
||||||
|
Browser: row.Browser,
|
||||||
|
IP: row.Ip,
|
||||||
|
Start: row.Start,
|
||||||
|
Version: row.Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
} else {
|
||||||
|
createdAnswers = append(createdAnswers, createdAnswer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
return nil, errs
|
||||||
|
}
|
||||||
|
|
||||||
|
return createdAnswers, errs
|
||||||
|
}
|
39
dal/db_query/queries.sql
Normal file
39
dal/db_query/queries.sql
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
-- name: GetQuestionListByIDs :many
|
||||||
|
SELECT * FROM question WHERE id = ANY($1::int[]) AND deleted = FALSE;
|
||||||
|
|
||||||
|
-- name: InsertQuestion :one
|
||||||
|
INSERT INTO question (
|
||||||
|
quiz_id,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
questiontype,
|
||||||
|
required,
|
||||||
|
page,
|
||||||
|
content,
|
||||||
|
parent_ids,
|
||||||
|
updated_at,
|
||||||
|
session,
|
||||||
|
auditory
|
||||||
|
)
|
||||||
|
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11)
|
||||||
|
RETURNING id, created_at, updated_at;
|
||||||
|
|
||||||
|
-- name: InsertAnswers :one
|
||||||
|
INSERT INTO answer(
|
||||||
|
content,
|
||||||
|
quiz_id,
|
||||||
|
question_id,
|
||||||
|
fingerprint,
|
||||||
|
session,
|
||||||
|
result,
|
||||||
|
email,
|
||||||
|
device_type,
|
||||||
|
device,
|
||||||
|
os,
|
||||||
|
browser,
|
||||||
|
ip,
|
||||||
|
start,
|
||||||
|
utm,
|
||||||
|
version
|
||||||
|
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15)
|
||||||
|
RETURNING *;
|
24
dal/schema/000001_init.down.sql
Normal file
24
dal/schema/000001_init.down.sql
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
-- Drop indexes
|
||||||
|
DROP INDEX IF EXISTS subquizes;
|
||||||
|
DROP INDEX IF EXISTS birthtime;
|
||||||
|
DROP INDEX IF EXISTS groups;
|
||||||
|
DROP INDEX IF EXISTS timeouted;
|
||||||
|
DROP INDEX IF EXISTS active ON quiz;
|
||||||
|
DROP INDEX IF EXISTS questiontype;
|
||||||
|
DROP INDEX IF EXISTS required;
|
||||||
|
DROP INDEX IF EXISTS relation;
|
||||||
|
DROP INDEX IF EXISTS active ON question;
|
||||||
|
|
||||||
|
-- Drop tables
|
||||||
|
DROP TABLE IF EXISTS privileges;
|
||||||
|
DROP TABLE IF EXISTS answer;
|
||||||
|
DROP TABLE IF EXISTS question;
|
||||||
|
DROP TABLE IF EXISTS quiz;
|
||||||
|
DROP TABLE IF EXISTS account;
|
||||||
|
|
||||||
|
-- Drop types
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
DROP TYPE IF EXISTS question_type;
|
||||||
|
DROP TYPE IF EXISTS quiz_status;
|
||||||
|
END$$;
|
120
dal/schema/000001_init.up.sql
Normal file
120
dal/schema/000001_init.up.sql
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
-- Create types
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'question_type') THEN
|
||||||
|
CREATE TYPE question_type AS ENUM (
|
||||||
|
'variant',
|
||||||
|
'images',
|
||||||
|
'varimg',
|
||||||
|
'emoji',
|
||||||
|
'text',
|
||||||
|
'select',
|
||||||
|
'date',
|
||||||
|
'number',
|
||||||
|
'file',
|
||||||
|
'page',
|
||||||
|
'rating'
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'quiz_status') THEN
|
||||||
|
CREATE TYPE quiz_status AS ENUM (
|
||||||
|
'draft',
|
||||||
|
'template',
|
||||||
|
'stop',
|
||||||
|
'start',
|
||||||
|
'timeout',
|
||||||
|
'offlimit'
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
|
END$$;
|
||||||
|
|
||||||
|
-- Create tables
|
||||||
|
CREATE TABLE IF NOT EXISTS account (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
user_id VARCHAR(24),
|
||||||
|
email VARCHAR(50),
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
deleted BOOLEAN DEFAULT false
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS quiz (
|
||||||
|
id bigserial UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
qid uuid DEFAULT uuid_generate_v4(),
|
||||||
|
accountid varchar(30) NOT NULL,
|
||||||
|
deleted boolean DEFAULT false,
|
||||||
|
archived boolean DEFAULT false,
|
||||||
|
fingerprinting boolean DEFAULT false,
|
||||||
|
repeatable boolean DEFAULT false,
|
||||||
|
note_prevented boolean DEFAULT false,
|
||||||
|
mail_notifications boolean DEFAULT false,
|
||||||
|
unique_answers boolean DEFAULT false,
|
||||||
|
super boolean DEFAULT false,
|
||||||
|
group_id bigint DEFAULT 0,
|
||||||
|
name varchar(280),
|
||||||
|
description text,
|
||||||
|
config text,
|
||||||
|
status quiz_status DEFAULT 'draft',
|
||||||
|
limit_answers integer DEFAULT 0,
|
||||||
|
due_to integer DEFAULT 0,
|
||||||
|
time_of_passing integer DEFAULT 0,
|
||||||
|
pausable boolean DEFAULT false,
|
||||||
|
version smallint DEFAULT 0,
|
||||||
|
version_comment text DEFAULT '',
|
||||||
|
parent_ids integer[],
|
||||||
|
created_at timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
questions_count integer DEFAULT 0,
|
||||||
|
answers_count integer DEFAULT 0,
|
||||||
|
average_time_passing integer DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS question (
|
||||||
|
id bigserial UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
quiz_id bigint NOT NULL,
|
||||||
|
title varchar(512) NOT NULL,
|
||||||
|
description text,
|
||||||
|
questiontype question_type DEFAULT 'text',
|
||||||
|
required boolean DEFAULT false,
|
||||||
|
deleted boolean DEFAULT false,
|
||||||
|
page smallint DEFAULT 0,
|
||||||
|
content text,
|
||||||
|
version smallint DEFAULT 0,
|
||||||
|
parent_ids integer[],
|
||||||
|
created_at timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
CONSTRAINT quiz_relation FOREIGN KEY(quiz_id) REFERENCES quiz(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS answer (
|
||||||
|
id bigserial UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
content text,
|
||||||
|
quiz_id bigint NOT NULL REFERENCES quiz(id),
|
||||||
|
question_id bigint NOT NULL REFERENCES question(id),
|
||||||
|
fingerprint varchar(1024),
|
||||||
|
session varchar(20),
|
||||||
|
created_at timestamp DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS privileges (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
privilegeID VARCHAR(50),
|
||||||
|
account_id UUID,
|
||||||
|
privilege_name VARCHAR(255),
|
||||||
|
amount INT,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (account_id) REFERENCES account (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create indexes
|
||||||
|
CREATE INDEX IF NOT EXISTS active ON question(deleted) WHERE deleted=false;
|
||||||
|
CREATE INDEX IF NOT EXISTS relation ON question(quiz_id DESC);
|
||||||
|
CREATE INDEX IF NOT EXISTS required ON question(required DESC);
|
||||||
|
CREATE INDEX IF NOT EXISTS questiontype ON question(questiontype);
|
||||||
|
CREATE INDEX IF NOT EXISTS active ON quiz(deleted, archived, status) WHERE deleted = false AND archived = false AND status = 'start';
|
||||||
|
CREATE INDEX IF NOT EXISTS timeouted ON quiz(due_to DESC) WHERE deleted = false AND due_to <> 0 AND status <> 'timeout';
|
||||||
|
CREATE INDEX IF NOT EXISTS groups ON quiz(super) WHERE super = true;
|
||||||
|
CREATE INDEX IF NOT EXISTS birthtime ON quiz(created_at DESC);
|
||||||
|
CREATE INDEX IF NOT EXISTS subquizes ON quiz(group_id DESC) WHERE group_id <> 0;
|
1
dal/schema/000002_init.down.sql
Normal file
1
dal/schema/000002_init.down.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE answer DROP COLUMN IF EXISTS result;
|
1
dal/schema/000002_init.up.sql
Normal file
1
dal/schema/000002_init.up.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE answer ADD COLUMN result BOOLEAN DEFAULT FALSE;
|
1
dal/schema/000003_init.down.sql
Normal file
1
dal/schema/000003_init.down.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE quiz DROP COLUMN IF EXISTS sessions_count;
|
1
dal/schema/000003_init.up.sql
Normal file
1
dal/schema/000003_init.up.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE quiz ADD COLUMN sessions_count integer;
|
2
dal/schema/000004_init.down.sql
Normal file
2
dal/schema/000004_init.down.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE quiz DROP COLUMN IF EXISTS new;
|
||||||
|
ALTER TABLE quiz DROP COLUMN IF EXISTS deleted;
|
2
dal/schema/000004_init.up.sql
Normal file
2
dal/schema/000004_init.up.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE answer ADD COLUMN new BOOLEAN DEFAULT TRUE;
|
||||||
|
ALTER TABLE answer ADD COLUMN deleted BOOLEAN DEFAULT FALSE;
|
2
dal/schema/000005_init.down.sql
Normal file
2
dal/schema/000005_init.down.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE answer DROP COLUMN IF EXISTS email;
|
||||||
|
DROP INDEX IF EXISTS answer_email_unique_idx;
|
2
dal/schema/000005_init.up.sql
Normal file
2
dal/schema/000005_init.up.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE answer ADD COLUMN email VARCHAR(50) NOT NULL DEFAULT '';
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS answer_email_unique_idx ON answer (quiz_id, email) WHERE email <> '';
|
6
dal/schema/000006_init.down.sql
Normal file
6
dal/schema/000006_init.down.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
ALTER TABLE answer
|
||||||
|
DROP COLUMN device_type,
|
||||||
|
DROP COLUMN device,
|
||||||
|
DROP COLUMN os,
|
||||||
|
DROP COLUMN browser,
|
||||||
|
DROP COLUMN ip;
|
6
dal/schema/000006_init.up.sql
Normal file
6
dal/schema/000006_init.up.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
ALTER TABLE answer
|
||||||
|
ADD COLUMN device_type VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
|
ADD COLUMN device VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
ADD COLUMN os VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
ADD COLUMN browser VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
ADD COLUMN ip VARCHAR(50) NOT NULL DEFAULT '';
|
2
dal/schema/000007_init.down.sql
Normal file
2
dal/schema/000007_init.down.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE answer
|
||||||
|
DROP COLUMN start;
|
2
dal/schema/000007_init.up.sql
Normal file
2
dal/schema/000007_init.up.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE answer
|
||||||
|
ADD COLUMN start BOOLEAN NOT NULL DEFAULT FALSE;
|
4
dal/schema/000008_init.down.sql
Normal file
4
dal/schema/000008_init.down.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE answer
|
||||||
|
ALTER COLUMN device TYPE VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
ALTER COLUMN os TYPE VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
ALTER COLUMN browser TYPE VARCHAR(100) NOT NULL DEFAULT '',
|
4
dal/schema/000008_init.up.sql
Normal file
4
dal/schema/000008_init.up.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE answer
|
||||||
|
ALTER COLUMN device TYPE VARCHAR(1024),
|
||||||
|
ALTER COLUMN os TYPE VARCHAR(1024),
|
||||||
|
ALTER COLUMN browser TYPE VARCHAR(1024);
|
4
dal/schema/000009_init.down.sql
Normal file
4
dal/schema/000009_init.down.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE answer
|
||||||
|
ALTER COLUMN device VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
ALTER COLUMN os VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
ALTER COLUMN browser VARCHAR(100) NOT NULL DEFAULT '',
|
4
dal/schema/000009_init.up.sql
Normal file
4
dal/schema/000009_init.up.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE answer
|
||||||
|
ALTER COLUMN device TYPE VARCHAR(512),
|
||||||
|
ALTER COLUMN os TYPE VARCHAR(512),
|
||||||
|
ALTER COLUMN browser TYPE VARCHAR(512);
|
31
dal/schema/000010_init.down.sql
Normal file
31
dal/schema/000010_init.down.sql
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
DROP INDEX IF EXISTS idx_unique_users;
|
||||||
|
DROP INDEX IF EXISTS idx_unique_pipeline;
|
||||||
|
DROP INDEX IF EXISTS idx_unique_step;
|
||||||
|
DROP INDEX IF EXISTS idx_unique_field;
|
||||||
|
DROP INDEX IF EXISTS idx_unique_tag;
|
||||||
|
DROP INDEX IF EXISTS idx_unique_rules;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS amoCRMStatuses;
|
||||||
|
DROP TABLE IF EXISTS rules;
|
||||||
|
DROP TABLE IF EXISTS utms;
|
||||||
|
DROP TABLE IF EXISTS tags;
|
||||||
|
DROP TABLE IF EXISTS fields;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'entitytype') THEN
|
||||||
|
DROP TYPE EntityType;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'fieldtype') THEN
|
||||||
|
DROP TYPE FieldType;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS steps;
|
||||||
|
DROP TABLE IF EXISTS pipelines;
|
||||||
|
DROP TABLE IF EXISTS tokens;
|
||||||
|
DROP TABLE IF EXISTS users;
|
119
dal/schema/000010_init.up.sql
Normal file
119
dal/schema/000010_init.up.sql
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS tokens (
|
||||||
|
AccountID VARCHAR(30) PRIMARY KEY, -- связь с users AccountID неявная посредством join
|
||||||
|
RefreshToken TEXT NOT NULL ,
|
||||||
|
AccessToken TEXT NOT NULL ,
|
||||||
|
AuthCode TEXT NOT NULL , -- код авторизации который получаем при вебхук
|
||||||
|
Expiration TIMESTAMP NOT NULL, -- время истечения токенов
|
||||||
|
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AccountID VARCHAR(30) NOT NULL DEFAULT '', -- id квизе из токена
|
||||||
|
AmoID INT NOT NULL , -- id в амо
|
||||||
|
Name VARCHAR(512) NOT NULL DEFAULT '', -- имя в амо
|
||||||
|
Email VARCHAR(50) NOT NULL DEFAULT '', -- почта в амо
|
||||||
|
Role INT NOT NULL DEFAULT 0, -- роль в амо
|
||||||
|
"Group" INT NOT NULL DEFAULT 0, -- вложенная структура так как в амо группы хранятся массивом структур
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
Subdomain VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
|
AmoUserID INT NOT NULL , -- id пользователя который подключал интеграцию
|
||||||
|
Country VARCHAR(50) NOT NULL DEFAULT '' -- страна в амо
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS pipelines (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AmoID INT NOT NULL , --id воронки в амо
|
||||||
|
AccountID INT NOT NULL , --id аккаунта в амо связь с таблицей users AmoID неявная посредством join
|
||||||
|
Name VARCHAR(512) NOT NULL DEFAULT '', --название воронки в амо
|
||||||
|
IsArchive BOOLEAN NOT NULL DEFAULT FALSE, --флаг архивной воронки в амо
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS steps (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AmoID INT NOT NULL, --id шага воронки в амо
|
||||||
|
PipelineID INT NOT NULL, --id воронки AmoID pipelines неявная посредством join
|
||||||
|
AccountID INT NOT NULL, --id аккаунта в амо связь с таблицей users AmoID неявная посредством join
|
||||||
|
Name VARCHAR(512) NOT NULL DEFAULT '', --название воронки в амо
|
||||||
|
Color VARCHAR(50) NOT NULL DEFAULT '', --цвет шага в амо*
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'entitytype') THEN
|
||||||
|
CREATE TYPE EntityType AS ENUM ('leads', 'contacts', 'companies', 'customers');
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'fieldtype') THEN
|
||||||
|
CREATE TYPE FieldType AS ENUM ('text', 'numeric', 'checkbox', 'select', 'multiselect', 'date', 'url', 'textarea', 'radiobutton', 'streetaddress', 'smart_address', 'birthday', 'legal_entity', 'date_time', 'price', 'category', 'items', 'tracking_data', 'linked_entity', 'chained_list', 'monetary', 'file', 'payer', 'supplier', 'multitext');
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS fields (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AmoID INT NOT NULL, -- айдишник кастомного поля в амо
|
||||||
|
Code VARCHAR(255) NOT NULL DEFAULT '', -- кодовое слово в амо
|
||||||
|
AccountID INT NOT NULL, -- id аккаунта в амо связь с таблицей users AmoID неявная посредством join
|
||||||
|
Name VARCHAR(512) NOT NULL DEFAULT '', -- название воронки в амо
|
||||||
|
Entity EntityType NOT NULL, -- тип сущности в амо, для которой это кастомное поле
|
||||||
|
Type FieldType NOT NULL, -- тип поля
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS tags (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AmoID INT NOT NULL, -- айдишник тега в амо
|
||||||
|
AccountID INT NOT NULL, -- id аккаунта в амо связь с таблицей users AmoID неявная посредством join
|
||||||
|
Entity EntityType NOT NULL, -- сущность, к которой принадлежит этот тег
|
||||||
|
Name VARCHAR(512) NOT NULL DEFAULT '', -- название тега в амо
|
||||||
|
Color VARCHAR(50) NOT NULL DEFAULT '', -- цвет тега в амо
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS utms (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AmoFieldID INT NOT NULL DEFAULT 0, -- id field в амо
|
||||||
|
QuizID INT NOT NULL, -- id опроса
|
||||||
|
AccountID INT NOT NULL, -- id аккаунта в амо AMOID
|
||||||
|
Name VARCHAR(512) NOT NULL DEFAULT '', -- название utm
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS rules (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AccountID INT NOT NULL, -- id аккаунта в амо AMOID
|
||||||
|
QuizID INT NOT NULL, -- id опроса
|
||||||
|
PerformerID INT NOT NULL, -- айдишник ответственного за сделку
|
||||||
|
PipelineID INT NOT NULL, --id воронки AmoID pipelines неявная посредством join
|
||||||
|
StepID INT NOT NULL , -- id этапа steps AmoID join
|
||||||
|
UTMS INTEGER[], -- список UTM для этого опроса id utm
|
||||||
|
FieldsRule JSONB NOT NULL DEFAULT '{}', -- вложенная структура
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX idx_unique_users ON users (amoID);
|
||||||
|
CREATE UNIQUE INDEX idx_unique_pipeline ON pipelines (amoID, accountID);
|
||||||
|
CREATE UNIQUE INDEX idx_unique_step ON steps (amoID, accountID, PipelineID);
|
||||||
|
CREATE UNIQUE INDEX idx_unique_field ON fields (amoID, accountID, entity);
|
||||||
|
CREATE UNIQUE INDEX idx_unique_tag ON tags (amoID, accountID, entity);
|
||||||
|
CREATE UNIQUE INDEX idx_unique_rules ON rules (accountID, QuizID);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS amoCRMStatuses (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AccountID INT NOT NULL, -- id аккаунта в амо
|
||||||
|
DealID INT NOT NULL, -- id сделки в которую добавлялось
|
||||||
|
AnswerID BIGINT NOT NULL REFERENCES answer(id), -- id true result который вызвал действие
|
||||||
|
Status TEXT NOT NULL DEFAULT '', -- запись о ошибке, либо успехе
|
||||||
|
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
15
dal/schema/000011_init.down.sql
Normal file
15
dal/schema/000011_init.down.sql
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
ALTER TABLE answer
|
||||||
|
DROP COLUMN utm;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS utms (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AmoFieldID INT NOT NULL DEFAULT 0, -- id field в амо
|
||||||
|
QuizID INT NOT NULL, -- id опроса
|
||||||
|
AccountID INT NOT NULL, -- id аккаунта в амо AMOID
|
||||||
|
Name VARCHAR(512) NOT NULL DEFAULT '', -- название utm
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE rules
|
||||||
|
ADD COLUMN UTMS INTEGER[];
|
5
dal/schema/000011_init.up.sql
Normal file
5
dal/schema/000011_init.up.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
ALTER TABLE answer
|
||||||
|
ADD COLUMN utm jsonb NOT NULL DEFAULT '{}';
|
||||||
|
DROP TABLE IF EXISTS utms;
|
||||||
|
ALTER TABLE rules
|
||||||
|
DROP COLUMN IF EXISTS UTMS;
|
4
dal/schema/000012_init.down.sql
Normal file
4
dal/schema/000012_init.down.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
DROP INDEX IF EXISTS idx_unique_users;
|
||||||
|
DROP INDEX IF EXISTS idx_unique_rules;
|
||||||
|
CREATE UNIQUE INDEX idx_unique_users ON users (amoID);
|
||||||
|
CREATE UNIQUE INDEX idx_unique_rules ON rules (accountID, QuizID);
|
4
dal/schema/000012_init.up.sql
Normal file
4
dal/schema/000012_init.up.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
DROP INDEX IF EXISTS idx_unique_users;
|
||||||
|
DROP INDEX IF EXISTS idx_unique_rules;
|
||||||
|
CREATE UNIQUE INDEX idx_unique_users ON users (amoID) WHERE Deleted = false;
|
||||||
|
CREATE UNIQUE INDEX idx_unique_rules ON rules (accountID, QuizID) WHERE Deleted = false;
|
4
dal/schema/000013_init.down.sql
Normal file
4
dal/schema/000013_init.down.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE rules
|
||||||
|
DROP COLUMN IF EXISTS TagsToAdd;
|
||||||
|
ALTER TABLE users
|
||||||
|
DROP COLUMN IF EXISTS DriveURL;
|
4
dal/schema/000013_init.up.sql
Normal file
4
dal/schema/000013_init.up.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE rules
|
||||||
|
ADD COLUMN TagsToAdd JSONB NOT NULL DEFAULT '{}';
|
||||||
|
ALTER TABLE users
|
||||||
|
ADD COLUMN DriveURL text NOT NULL DEFAULT '';
|
20
dal/schema/000014_init.down.sql
Normal file
20
dal/schema/000014_init.down.sql
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
DROP TABLE IF EXISTS usersAmo;
|
||||||
|
DROP INDEX IF EXISTS idx_unique_accountsAmo;
|
||||||
|
DROP TABLE IF EXISTS accountsAmo;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AccountID VARCHAR(30) NOT NULL DEFAULT '', -- id квизе из токена
|
||||||
|
AmoID INT NOT NULL , -- id в амо
|
||||||
|
Name VARCHAR(512) NOT NULL DEFAULT '', -- имя в амо
|
||||||
|
Email VARCHAR(50) NOT NULL DEFAULT '', -- почта в амо
|
||||||
|
Role INT NOT NULL DEFAULT 0, -- роль в амо
|
||||||
|
"Group" INT NOT NULL DEFAULT 0, -- вложенная структура так как в амо группы хранятся массивом структур
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
Subdomain VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
|
AmoUserID INT NOT NULL , -- id пользователя который подключал интеграцию
|
||||||
|
Country VARCHAR(50) NOT NULL DEFAULT '' -- страна в амо
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX idx_unique_users ON users (amoID) WHERE Deleted = false;
|
28
dal/schema/000014_init.up.sql
Normal file
28
dal/schema/000014_init.up.sql
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
DROP TABLE IF EXISTS users;
|
||||||
|
DROP INDEX IF EXISTS idx_unique_users;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS accountsAmo (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AccountID VARCHAR(30) NOT NULL DEFAULT '', -- ID аккаунта у нас
|
||||||
|
AmoID INT NOT NULL, -- ID "компании" в амо
|
||||||
|
Name VARCHAR(512) NOT NULL DEFAULT '',
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
Subdomain VARCHAR(50) NOT NULL DEFAULT '', -- поддомен - пример https://penadigitaltech.amocrm.ru
|
||||||
|
Country VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
|
DriveURL VARCHAR(255) NOT NULL DEFAULT '' -- URL объктного хранилища
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX idx_unique_accountsAmo ON accountsAmo (amoID) WHERE Deleted = false;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS usersAmo (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AmoID INT NOT NULL, -- ID компании в амо (внешний ключ)
|
||||||
|
AmoUserID INT NOT NULL, -- ID пользователя в амо
|
||||||
|
Name VARCHAR(512) NOT NULL DEFAULT '',
|
||||||
|
Email VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
|
Role INT NOT NULL DEFAULT 0,
|
||||||
|
"Group" INT NOT NULL DEFAULT 0,
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
0
dal/schema/000015_init.down.sql
Normal file
0
dal/schema/000015_init.down.sql
Normal file
19
dal/schema/000015_init.up.sql
Normal file
19
dal/schema/000015_init.up.sql
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
UPDATE answer
|
||||||
|
SET content =
|
||||||
|
CASE
|
||||||
|
WHEN content ~ '<tr>|<td>' THEN
|
||||||
|
regexp_replace(content, '<\/?tr[^>]*>|<\/?td[^>]*>', '', 'g')
|
||||||
|
WHEN content ~ '<a download>[^<]+</a>' THEN
|
||||||
|
regexp_replace(content, '<a download>([^<]+)</a>', '\1', 'g')
|
||||||
|
WHEN content ~ '<img[^>]*src="([^"]*)"[^>]*' THEN
|
||||||
|
regexp_replace(content, '<img[^>]*src="\s*"[^>]*', '', 'g')
|
||||||
|
ELSE content
|
||||||
|
END;
|
||||||
|
|
||||||
|
UPDATE answer
|
||||||
|
SET content =
|
||||||
|
CASE
|
||||||
|
WHEN content ~ '<img' THEN
|
||||||
|
regexp_replace(content, '(.*?)(<img[^>]*src=["'']?([^"''>]+)["'']?[^>]*>)', '\1\3', 'g')
|
||||||
|
ELSE content
|
||||||
|
END;
|
1
dal/schema/000016_init.down.sql
Normal file
1
dal/schema/000016_init.down.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
DROP TABLE IF EXISTS amoContact;
|
6
dal/schema/000016_init.up.sql
Normal file
6
dal/schema/000016_init.up.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS amoContact (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AccountID INT NOT NULL, -- ID "компании" в амо
|
||||||
|
AmoID INT NOT NULL, -- ID контакта в амо
|
||||||
|
Field text NOT NULL DEFAULT '' -- значение чего то email? phone? etc
|
||||||
|
)
|
11
dal/schema/000017_init.down.sql
Normal file
11
dal/schema/000017_init.down.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
ALTER table question DROP column session;
|
||||||
|
ALTER TABLE account ADD column email varchar(50) NOT NULL default '';
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'leadtargettype') THEN
|
||||||
|
DROP TYPE LeadTargetType;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS leadtarget;
|
31
dal/schema/000017_init.up.sql
Normal file
31
dal/schema/000017_init.up.sql
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1 FROM pg_enum
|
||||||
|
WHERE enumlabel = 'ai' AND enumtypid = 'quiz_status'::regtype
|
||||||
|
) THEN
|
||||||
|
ALTER TYPE quiz_status ADD VALUE 'ai';
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
ALTER TABLE question ADD column session varchar(20) NOT NULL DEFAULT '';
|
||||||
|
|
||||||
|
AlTER TABLE account DROP column email;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'leadtargettype') THEN
|
||||||
|
CREATE TYPE LeadTargetType AS ENUM ('mail', 'telegram', 'whatsapp');
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS leadtarget(
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AccountID varchar(30) NOT NULL,
|
||||||
|
Type LeadTargetType NOT NULL,
|
||||||
|
QuizID integer NOT NULL DEFAULT 0,
|
||||||
|
Target text NOT NULL,
|
||||||
|
InviteLink text NOT NULL DEFAULT '',
|
||||||
|
Deleted boolean NOT NULL DEFAULT false,
|
||||||
|
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
12
dal/schema/000018_init.down.sql
Normal file
12
dal/schema/000018_init.down.sql
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
DROP TABLE IF EXISTS gigachatAudience;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS tgAccounts;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'tgAccountStatus') THEN
|
||||||
|
DROP TYPE TgAccountStatus;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DROP INDEX IF EXISTS idx_apiid_apihash;
|
29
dal/schema/000018_init.up.sql
Normal file
29
dal/schema/000018_init.up.sql
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS gigachatAudience (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
QuizID BIGINT NOT NULL,
|
||||||
|
Sex BOOLEAN NOT NULL,
|
||||||
|
Age VARCHAR(5) NOT NULL,
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
CONSTRAINT fk_quiz FOREIGN KEY (QuizID) REFERENCES quiz(ID)
|
||||||
|
);
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'tgAccountStatus') THEN
|
||||||
|
CREATE TYPE TgAccountStatus AS ENUM ('active', 'inactive', 'ban');
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS tgAccounts (
|
||||||
|
id bigserial primary key ,
|
||||||
|
ApiID integer not null,
|
||||||
|
ApiHash text not null ,
|
||||||
|
PhoneNumber text not null ,
|
||||||
|
Password text not null ,
|
||||||
|
Status TgAccountStatus not null,
|
||||||
|
Deleted bool not null default false,
|
||||||
|
CreatedAt timestamp not null default current_timestamp
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX idx_apiid_apihash ON tgAccounts (ApiID, ApiHash) WHERE Deleted = false;
|
11
dal/schema/000019_init.down.sql
Normal file
11
dal/schema/000019_init.down.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
ALTER TABLE account
|
||||||
|
ALTER COLUMN user_id DROP NOT NULL,
|
||||||
|
ALTER COLUMN created_at DROP NOT NULL,
|
||||||
|
ALTER COLUMN deleted DROP NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE privileges
|
||||||
|
ALTER COLUMN privilegeID DROP NOT NULL,
|
||||||
|
ALTER COLUMN account_id DROP NOT NULL,
|
||||||
|
ALTER COLUMN privilege_name DROP NOT NULL,
|
||||||
|
ALTER COLUMN amount DROP NOT NULL,
|
||||||
|
ALTER COLUMN created_at DROP NOT NULL;
|
11
dal/schema/000019_init.up.sql
Normal file
11
dal/schema/000019_init.up.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
ALTER TABLE account
|
||||||
|
ALTER COLUMN user_id SET NOT NULL,
|
||||||
|
ALTER COLUMN created_at SET NOT NULL,
|
||||||
|
ALTER COLUMN deleted SET NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE privileges
|
||||||
|
ALTER COLUMN privilegeID SET NOT NULL,
|
||||||
|
ALTER COLUMN account_id SET NOT NULL,
|
||||||
|
ALTER COLUMN privilege_name SET NOT NULL,
|
||||||
|
ALTER COLUMN amount SET NOT NULL,
|
||||||
|
ALTER COLUMN created_at SET NOT NULL;
|
19
dal/schema/000020_init.down.sql
Normal file
19
dal/schema/000020_init.down.sql
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
DROP TABLE IF EXISTS telegram_integration;
|
||||||
|
DROP TABLE IF EXISTS respondent_state;
|
||||||
|
DROP TABLE IF EXISTS telegram_integration_instance;
|
||||||
|
drop table if exists telegram_user_quiz_result;
|
||||||
|
DROP INDEX results_for_quiz;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'bot_status') THEN
|
||||||
|
DROP TYPE bot_status;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'user_result_tg_status') THEN
|
||||||
|
DROP TYPE user_result_tg_status;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
57
dal/schema/000020_init.up.sql
Normal file
57
dal/schema/000020_init.up.sql
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'bot_status') THEN
|
||||||
|
CREATE TYPE bot_status AS ENUM ('active','stopped', 'banned');
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'user_result_tg_status') THEN
|
||||||
|
CREATE TYPE user_result_tg_status AS ENUM ('in_progress','completed');
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS results_for_quiz ON answer(quiz_id, result);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS telegram_integration(
|
||||||
|
id bigserial unique not null primary key,
|
||||||
|
accountid varchar(30) NOT NULL, -- связь с аккаунтом квиза
|
||||||
|
quizID integer NOT NULL , -- айдишник квиза, с которым связываем интеграцию
|
||||||
|
bot_token text NOT NULL, -- токен бота
|
||||||
|
bot_name text NOT NULL DEFAULT '', -- имя бота
|
||||||
|
repeatable boolean DEFAULT false, -- флаг возможности повторить опрос
|
||||||
|
deleted boolean NOT NULL default false, -- флаг удаленного
|
||||||
|
status bot_status NOT NULL DEFAULT 'active',
|
||||||
|
instance_id integer NOT NULL default 0
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS respondent_state(
|
||||||
|
id bigserial unique not null primary key,
|
||||||
|
telegram_id integer NOT NULL, -- айдишник пользователя в телеграме, скорее всего чат id
|
||||||
|
quizID integer NOT NULL, -- айдишник квиза, который проходится этим респондентом
|
||||||
|
state bigint NOT NULL,
|
||||||
|
lang text NOT NULL default '', -- язык опрашиваемого
|
||||||
|
contact text NOT NULL default '', -- ник пользователя в телеге, если доступен
|
||||||
|
finish boolean not null default false, -- статус, пройден опрос или нет
|
||||||
|
session varchar(20) -- сессия пользователя
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS telegram_integration_instance(
|
||||||
|
id bigserial unique not null primary key,
|
||||||
|
checkout bigint not null , -- время "подтверждения активности". в идеале должно быть актуальным, но отличаться от всех остальных минимум на 10 секунд. т.е. если у нас есть бот с временем в 10:10:10 и бот с временем в 10:10:31, а сейчас 10:10:32, то валидные слоты это 10:10:21 и 10:10:41. но как это сделать я не знаю. как вариант, можно просто взять бот с максимальным временем и сделать ему +10. и наверное это правильныйй вариант
|
||||||
|
limited integer not null, --константа с лимитом ботов
|
||||||
|
amount integer not null -- актуальное количество ботов
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS telegram_user_quiz_result(
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
bot_id BIGINT NOT NULL,
|
||||||
|
quiz_id BIGINT NOT NULL,
|
||||||
|
current_field TEXT,
|
||||||
|
user_answer TEXT DEFAULT '',
|
||||||
|
state user_result_tg_status not null default 'in_progress',
|
||||||
|
session varchar(20) NOT NULL ,
|
||||||
|
question_id bigint NOT NULL, -- id вопроса результата
|
||||||
|
iter integer not null
|
||||||
|
)
|
35
dal/schema/000021_init.down.sql
Normal file
35
dal/schema/000021_init.down.sql
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
DROP TABLE IF EXISTS BitrixTokens;
|
||||||
|
DROP TABLE IF EXISTS StepBitrix;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS PipelineBitrix;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS BitrixAccounts;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS BitrixAccountUsers;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS BitrixFields;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS BitrixRule;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS bitrixCRMStatuses;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS bitrixContact;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'CustomFieldsType') THEN
|
||||||
|
DROP TYPE CustomFieldsType;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'FieldsType') THEN
|
||||||
|
DROP TYPE FieldsType;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DROP INDEX IF EXISTS idx_unique_pipeline_bitrix;
|
||||||
|
DROP INDEX IF EXISTS idx_unique_step_bitrix;
|
||||||
|
DROP INDEX IF EXISTS idx_unique_field_bitrix;
|
||||||
|
ALTER TABLE answer DROP COLUMN IF EXISTS version;
|
149
dal/schema/000021_init.up.sql
Normal file
149
dal/schema/000021_init.up.sql
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS BitrixTokens (
|
||||||
|
AccountID VARCHAR(30) PRIMARY KEY, -- связь с users AccountID неявная посредством join
|
||||||
|
RefreshToken TEXT NOT NULL ,
|
||||||
|
AccessToken TEXT NOT NULL ,
|
||||||
|
AuthCode TEXT NOT NULL , -- код авторизации который получаем при вебхук
|
||||||
|
Expiration TIMESTAMP NOT NULL, -- время истечения токенов
|
||||||
|
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'FieldsType') THEN
|
||||||
|
CREATE TYPE FieldsType AS ENUM (
|
||||||
|
'CRM_LEAD',
|
||||||
|
'CRM_COMPANY',
|
||||||
|
'CRM_CONTACT',
|
||||||
|
'CRM_DEAL',
|
||||||
|
'CRM_INVOICE',
|
||||||
|
'CRM_SMART_INVOICE',
|
||||||
|
'CRM_QUOTE',
|
||||||
|
'CRM_REQUISITE'
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'CustomFieldsType') THEN
|
||||||
|
CREATE TYPE CustomFieldsType AS ENUM (
|
||||||
|
'string',
|
||||||
|
'integer',
|
||||||
|
'double',
|
||||||
|
'boolean',
|
||||||
|
'datetime',
|
||||||
|
'enumeration',
|
||||||
|
'iblock_section',
|
||||||
|
'iblock_element',
|
||||||
|
'employee',
|
||||||
|
'crm_status',
|
||||||
|
'crm',
|
||||||
|
'address',
|
||||||
|
'money',
|
||||||
|
'url',
|
||||||
|
'file',
|
||||||
|
'crm_pena_tag'
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS BitrixFields (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
BitrixID VARCHAR(255) NOT NULL, -- Айдишник field в битриксе
|
||||||
|
AccountID VARCHAR(255) NOT NULL,-- ID портала битрикса
|
||||||
|
EntityID FieldsType NOT NULL,-- тип поля
|
||||||
|
FieldName VARCHAR(255) NOT NULL,-- имя поля
|
||||||
|
EditFromLabel VARCHAR(255) NOT NULL,-- заголовок вопроса
|
||||||
|
FieldType CustomFieldsType NOT NULL, -- тип поля
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS BitrixAccountUsers (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AccountID VARCHAR(255) NOT NULL, -- ID портала битрикса
|
||||||
|
BitrixIDUserID VARCHAR(255) NOT NULL, -- ID пользователя в битриксе
|
||||||
|
Name VARCHAR(255) NOT NULL default '', -- Имя
|
||||||
|
LastName VARCHAR(255) NOT NULL default '',-- Фамилия
|
||||||
|
SecondName VARCHAR(255) NOT NULL default '', -- Отчество
|
||||||
|
Title VARCHAR(255) NOT NULL default '',
|
||||||
|
Email VARCHAR(255) NOT NULL default '', -- Почта
|
||||||
|
UFDepartment INT[], -- Массив департаментов
|
||||||
|
WorkPosition VARCHAR(255) NOT NULL default '', -- Должность
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS BitrixAccounts (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AccountID VARCHAR(30) NOT NULL, -- ID аккаунта у нас
|
||||||
|
BitrixID VARCHAR(255) NOT NULL, -- ID портала битрикса
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
Subdomain VARCHAR(50) NOT NULL -- поддомен
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS PipelineBitrix (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
BitrixID INT NOT NULL, -- Айдишник воронки в битриксе
|
||||||
|
AccountID VARCHAR(255) NOT NULL, -- ID портала битрикса
|
||||||
|
Name VARCHAR(255) NOT NULL, -- Название воронки
|
||||||
|
EntityTypeId INT NOT NULL, -- Тип по номерам
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
CONSTRAINT validEntityType CHECK (EntityTypeId IN (1, 2, 3, 4, 5, 7, 8, 31))
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS StepBitrix (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AccountID VARCHAR(255) NOT NULL, -- ID портала битрикса
|
||||||
|
BitrixID VARCHAR(255) NOT NULL, -- Айдишник состояния в битриксе
|
||||||
|
EntityID VARCHAR(255) NOT NULL, -- Тип сущности
|
||||||
|
StatusID VARCHAR(255) NOT NULL, -- Текстовый формат ID статуса
|
||||||
|
Name VARCHAR(255) NOT NULL default '', -- Название
|
||||||
|
NameInit VARCHAR(255) NOT NULL default '', -- возможно это изначальное название
|
||||||
|
Color VARCHAR(50) NOT NULL default '', -- Цвет
|
||||||
|
PipelineID INT NOT NULL, -- ID воронки
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS BitrixRule (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AccountID VARCHAR(255) NOT NULL, -- ID портала битрикса
|
||||||
|
QuizID INT NOT NULL, -- ID квиза на которое вешается правило
|
||||||
|
PerformerID VARCHAR(255) NOT NULL, -- ID пользователя в битриксе который ответсвенный
|
||||||
|
PipelineID INT NOT NULL, -- ID воронки
|
||||||
|
TypeID VARCHAR(255) NOT NULL, -- шаг сделки только с "ENTITY_ID":"DEAL_TYPE","STATUS_ID":"SALE"
|
||||||
|
StageID VARCHAR(255) NOT NULL, -- стадия сделки, шаг "ENTITY_ID":"DEAL_STAGE","STATUS_ID":"NEW"
|
||||||
|
SourceID VARCHAR(255) NOT NULL, -- тип источника, шаг "ENTITY_ID":"SOURCE","STATUS_ID":"CALL"
|
||||||
|
StatusID VARCHAR(255) NOT NULL, -- тип источника, шаг "ENTITY_ID":"STATUS","STATUS_ID":"IN_PROCESS"
|
||||||
|
FieldsRule JSONB NOT NULL DEFAULT '{}', -- вложенная структура
|
||||||
|
TagsToAdd JSONB NOT NULL DEFAULT '{}', -- структура тегов которые надо дбавлять
|
||||||
|
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
LeadFlag BOOLEAN NOT NULL DEFAULT FALSE -- если true то делаем лид а не сделку
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS bitrixCRMStatuses (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AccountID VARCHAR(255) NOT NULL, -- ID портала битрикса
|
||||||
|
DealID INT NOT NULL, -- id сделки или лида в которую добавлялось
|
||||||
|
AnswerID BIGINT NOT NULL REFERENCES answer(id), -- id true result который вызвал действие
|
||||||
|
Status TEXT NOT NULL DEFAULT '', -- запись о ошибке, либо успехе
|
||||||
|
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS bitrixContact (
|
||||||
|
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
AccountID VARCHAR(255) NOT NULL, -- ID "компании" в амо
|
||||||
|
BitrixID INT NOT NULL, -- ID контакта в амо
|
||||||
|
Field text NOT NULL DEFAULT '' -- значение чего то email? phone? etc
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX idx_unique_pipeline_bitrix ON PipelineBitrix (BitrixID, AccountID) WHERE Deleted = false;
|
||||||
|
CREATE UNIQUE INDEX idx_unique_step_bitrix ON StepBitrix (BitrixID, AccountID) WHERE Deleted = false;
|
||||||
|
CREATE UNIQUE INDEX idx_unique_field_bitrix ON BitrixFields (BitrixID, AccountID, EntityID);
|
||||||
|
ALTER TABLE answer ADD COLUMN version integer NOT NULL default 0;
|
1
dal/schema/000022_init.down.sql
Normal file
1
dal/schema/000022_init.down.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE question DROP COLUMN IF EXISTS auditory;
|
1
dal/schema/000022_init.up.sql
Normal file
1
dal/schema/000022_init.up.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE question ADD COLUMN auditory BIGINT NOT NULL DEFAULT 0;
|
0
dal/schema/000023_init.down.sql
Normal file
0
dal/schema/000023_init.down.sql
Normal file
14
dal/schema/000023_init.up.sql
Normal file
14
dal/schema/000023_init.up.sql
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
BEGIN;
|
||||||
|
ALTER TABLE gigachatAudience RENAME COLUMN Sex TO Sex_old;
|
||||||
|
ALTER TABLE gigachatAudience ADD COLUMN Sex INTEGER;
|
||||||
|
UPDATE gigachatAudience
|
||||||
|
SET Sex = CASE
|
||||||
|
WHEN Sex_old = FALSE THEN 0
|
||||||
|
WHEN Sex_old = TRUE THEN 1
|
||||||
|
ELSE 2
|
||||||
|
END;
|
||||||
|
ALTER TABLE gigachatAudience DROP COLUMN Sex_old;
|
||||||
|
ALTER TABLE gigachatAudience ALTER COLUMN Sex SET NOT NULL;
|
||||||
|
ALTER TABLE gigachatAudience
|
||||||
|
ADD CONSTRAINT check_sex_valid_values CHECK (Sex IN (0, 1, 2));
|
||||||
|
COMMIT;
|
1
dal/schema/000024_init.down.sql
Normal file
1
dal/schema/000024_init.down.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE quiz DROP COLUMN IF EXISTS gigachat;
|
1
dal/schema/000024_init.up.sql
Normal file
1
dal/schema/000024_init.up.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE quiz ADD COLUMN gigachat boolean NOT NULL DEFAULT false;
|
1
dal/schema/000025_init.down.sql
Normal file
1
dal/schema/000025_init.down.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
drop table if exists quiz_utm;
|
7
dal/schema/000025_init.up.sql
Normal file
7
dal/schema/000025_init.up.sql
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS quiz_utm (
|
||||||
|
id bigserial UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
quizID bigint not null,
|
||||||
|
utm text not null default '',
|
||||||
|
deleted boolean not null default false,
|
||||||
|
created_at TIMESTAMP not null DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
2
dal/schema/000026_init.down.sql
Normal file
2
dal/schema/000026_init.down.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
DROP INDEX IF EXISTS idx_quiz_privilege_unique;
|
||||||
|
drop table if exists quiz_privilege_usage;
|
10
dal/schema/000026_init.up.sql
Normal file
10
dal/schema/000026_init.up.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
CREATE TABLE quiz_privilege_usage (
|
||||||
|
id bigserial UNIQUE NOT NULL PRIMARY KEY,
|
||||||
|
quiz_id BIGINT NOT NULL REFERENCES quiz(id) ON DELETE CASCADE,
|
||||||
|
privilege_id VARCHAR(50) NOT NULL,
|
||||||
|
used_count INT NOT NULL DEFAULT 0,
|
||||||
|
created_at TIMESTAMP not null DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP not null DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX idx_quiz_privilege_unique ON quiz_privilege_usage (quiz_id, privilege_id);
|
31
dal/sqlcgen/db.go
Normal file
31
dal/sqlcgen/db.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// sqlc v1.29.0
|
||||||
|
|
||||||
|
package sqlcgen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DBTX interface {
|
||||||
|
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
|
||||||
|
PrepareContext(context.Context, string) (*sql.Stmt, error)
|
||||||
|
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
|
||||||
|
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(db DBTX) *Queries {
|
||||||
|
return &Queries{db: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Queries struct {
|
||||||
|
db DBTX
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
|
||||||
|
return &Queries{
|
||||||
|
db: tx,
|
||||||
|
}
|
||||||
|
}
|
400
dal/sqlcgen/models.go
Normal file
400
dal/sqlcgen/models.go
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// sqlc v1.29.0
|
||||||
|
|
||||||
|
package sqlcgen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Account struct {
|
||||||
|
ID uuid.UUID `db:"id" json:"id"`
|
||||||
|
UserID string `db:"user_id" json:"user_id"`
|
||||||
|
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Accountsamo struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Amoid int32 `db:"amoid" json:"amoid"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat time.Time `db:"createdat" json:"createdat"`
|
||||||
|
Subdomain string `db:"subdomain" json:"subdomain"`
|
||||||
|
Country string `db:"country" json:"country"`
|
||||||
|
Driveurl string `db:"driveurl" json:"driveurl"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Amocontact struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Accountid int32 `db:"accountid" json:"accountid"`
|
||||||
|
Amoid int32 `db:"amoid" json:"amoid"`
|
||||||
|
Field string `db:"field" json:"field"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Amocrmstatus struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Accountid int32 `db:"accountid" json:"accountid"`
|
||||||
|
Dealid int32 `db:"dealid" json:"dealid"`
|
||||||
|
Answerid int64 `db:"answerid" json:"answerid"`
|
||||||
|
Status string `db:"status" json:"status"`
|
||||||
|
Createdat sql.NullTime `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Answer struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Content sql.NullString `db:"content" json:"content"`
|
||||||
|
QuizID int64 `db:"quiz_id" json:"quiz_id"`
|
||||||
|
QuestionID int64 `db:"question_id" json:"question_id"`
|
||||||
|
Fingerprint sql.NullString `db:"fingerprint" json:"fingerprint"`
|
||||||
|
Session sql.NullString `db:"session" json:"session"`
|
||||||
|
CreatedAt sql.NullTime `db:"created_at" json:"created_at"`
|
||||||
|
Result sql.NullBool `db:"result" json:"result"`
|
||||||
|
New sql.NullBool `db:"new" json:"new"`
|
||||||
|
Deleted sql.NullBool `db:"deleted" json:"deleted"`
|
||||||
|
Email string `db:"email" json:"email"`
|
||||||
|
DeviceType string `db:"device_type" json:"device_type"`
|
||||||
|
Device string `db:"device" json:"device"`
|
||||||
|
Os string `db:"os" json:"os"`
|
||||||
|
Browser string `db:"browser" json:"browser"`
|
||||||
|
Ip string `db:"ip" json:"ip"`
|
||||||
|
Start bool `db:"start" json:"start"`
|
||||||
|
Utm json.RawMessage `db:"utm" json:"utm"`
|
||||||
|
Version int32 `db:"version" json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bitrixaccount struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Bitrixid string `db:"bitrixid" json:"bitrixid"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat time.Time `db:"createdat" json:"createdat"`
|
||||||
|
Subdomain string `db:"subdomain" json:"subdomain"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bitrixaccountuser struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Bitrixiduserid string `db:"bitrixiduserid" json:"bitrixiduserid"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
|
Lastname string `db:"lastname" json:"lastname"`
|
||||||
|
Secondname string `db:"secondname" json:"secondname"`
|
||||||
|
Title string `db:"title" json:"title"`
|
||||||
|
Email string `db:"email" json:"email"`
|
||||||
|
Ufdepartment []int32 `db:"ufdepartment" json:"ufdepartment"`
|
||||||
|
Workposition string `db:"workposition" json:"workposition"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat time.Time `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bitrixcontact struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Bitrixid int32 `db:"bitrixid" json:"bitrixid"`
|
||||||
|
Field string `db:"field" json:"field"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bitrixcrmstatus struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Dealid int32 `db:"dealid" json:"dealid"`
|
||||||
|
Answerid int64 `db:"answerid" json:"answerid"`
|
||||||
|
Status string `db:"status" json:"status"`
|
||||||
|
Createdat time.Time `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bitrixfield struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Bitrixid string `db:"bitrixid" json:"bitrixid"`
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Entityid interface{} `db:"entityid" json:"entityid"`
|
||||||
|
Fieldname string `db:"fieldname" json:"fieldname"`
|
||||||
|
Editfromlabel string `db:"editfromlabel" json:"editfromlabel"`
|
||||||
|
Fieldtype interface{} `db:"fieldtype" json:"fieldtype"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat time.Time `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bitrixrule struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Quizid int32 `db:"quizid" json:"quizid"`
|
||||||
|
Performerid string `db:"performerid" json:"performerid"`
|
||||||
|
Pipelineid int32 `db:"pipelineid" json:"pipelineid"`
|
||||||
|
Typeid string `db:"typeid" json:"typeid"`
|
||||||
|
Stageid string `db:"stageid" json:"stageid"`
|
||||||
|
Sourceid string `db:"sourceid" json:"sourceid"`
|
||||||
|
Statusid string `db:"statusid" json:"statusid"`
|
||||||
|
Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"`
|
||||||
|
Tagstoadd json.RawMessage `db:"tagstoadd" json:"tagstoadd"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat time.Time `db:"createdat" json:"createdat"`
|
||||||
|
Leadflag bool `db:"leadflag" json:"leadflag"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bitrixtoken struct {
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Refreshtoken string `db:"refreshtoken" json:"refreshtoken"`
|
||||||
|
Accesstoken string `db:"accesstoken" json:"accesstoken"`
|
||||||
|
Authcode string `db:"authcode" json:"authcode"`
|
||||||
|
Expiration time.Time `db:"expiration" json:"expiration"`
|
||||||
|
Createdat time.Time `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Field struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Amoid int32 `db:"amoid" json:"amoid"`
|
||||||
|
Code string `db:"code" json:"code"`
|
||||||
|
Accountid int32 `db:"accountid" json:"accountid"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
|
Entity interface{} `db:"entity" json:"entity"`
|
||||||
|
Type interface{} `db:"type" json:"type"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat sql.NullTime `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Gigachataudience struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Quizid int64 `db:"quizid" json:"quizid"`
|
||||||
|
Age string `db:"age" json:"age"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat sql.NullTime `db:"createdat" json:"createdat"`
|
||||||
|
Sex int32 `db:"sex" json:"sex"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Leadtarget struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Type interface{} `db:"type" json:"type"`
|
||||||
|
Quizid int32 `db:"quizid" json:"quizid"`
|
||||||
|
Target string `db:"target" json:"target"`
|
||||||
|
Invitelink string `db:"invitelink" json:"invitelink"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat time.Time `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pipeline struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Amoid int32 `db:"amoid" json:"amoid"`
|
||||||
|
Accountid int32 `db:"accountid" json:"accountid"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
|
Isarchive bool `db:"isarchive" json:"isarchive"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat sql.NullTime `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pipelinebitrix struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Bitrixid int32 `db:"bitrixid" json:"bitrixid"`
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
|
Entitytypeid int32 `db:"entitytypeid" json:"entitytypeid"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat time.Time `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Privilege struct {
|
||||||
|
ID int32 `db:"id" json:"id"`
|
||||||
|
Privilegeid string `db:"privilegeid" json:"privilegeid"`
|
||||||
|
AccountID uuid.UUID `db:"account_id" json:"account_id"`
|
||||||
|
PrivilegeName string `db:"privilege_name" json:"privilege_name"`
|
||||||
|
Amount int32 `db:"amount" json:"amount"`
|
||||||
|
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Question struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
QuizID int64 `db:"quiz_id" json:"quiz_id"`
|
||||||
|
Title string `db:"title" json:"title"`
|
||||||
|
Description sql.NullString `db:"description" json:"description"`
|
||||||
|
Questiontype interface{} `db:"questiontype" json:"questiontype"`
|
||||||
|
Required sql.NullBool `db:"required" json:"required"`
|
||||||
|
Deleted sql.NullBool `db:"deleted" json:"deleted"`
|
||||||
|
Page sql.NullInt16 `db:"page" json:"page"`
|
||||||
|
Content sql.NullString `db:"content" json:"content"`
|
||||||
|
Version sql.NullInt16 `db:"version" json:"version"`
|
||||||
|
ParentIds []int32 `db:"parent_ids" json:"parent_ids"`
|
||||||
|
CreatedAt sql.NullTime `db:"created_at" json:"created_at"`
|
||||||
|
UpdatedAt sql.NullTime `db:"updated_at" json:"updated_at"`
|
||||||
|
Session string `db:"session" json:"session"`
|
||||||
|
Auditory int64 `db:"auditory" json:"auditory"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Quiz struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Qid uuid.NullUUID `db:"qid" json:"qid"`
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Deleted sql.NullBool `db:"deleted" json:"deleted"`
|
||||||
|
Archived sql.NullBool `db:"archived" json:"archived"`
|
||||||
|
Fingerprinting sql.NullBool `db:"fingerprinting" json:"fingerprinting"`
|
||||||
|
Repeatable sql.NullBool `db:"repeatable" json:"repeatable"`
|
||||||
|
NotePrevented sql.NullBool `db:"note_prevented" json:"note_prevented"`
|
||||||
|
MailNotifications sql.NullBool `db:"mail_notifications" json:"mail_notifications"`
|
||||||
|
UniqueAnswers sql.NullBool `db:"unique_answers" json:"unique_answers"`
|
||||||
|
Super sql.NullBool `db:"super" json:"super"`
|
||||||
|
GroupID sql.NullInt64 `db:"group_id" json:"group_id"`
|
||||||
|
Name sql.NullString `db:"name" json:"name"`
|
||||||
|
Description sql.NullString `db:"description" json:"description"`
|
||||||
|
Config sql.NullString `db:"config" json:"config"`
|
||||||
|
Status interface{} `db:"status" json:"status"`
|
||||||
|
LimitAnswers sql.NullInt32 `db:"limit_answers" json:"limit_answers"`
|
||||||
|
DueTo sql.NullInt32 `db:"due_to" json:"due_to"`
|
||||||
|
TimeOfPassing sql.NullInt32 `db:"time_of_passing" json:"time_of_passing"`
|
||||||
|
Pausable sql.NullBool `db:"pausable" json:"pausable"`
|
||||||
|
Version sql.NullInt16 `db:"version" json:"version"`
|
||||||
|
VersionComment sql.NullString `db:"version_comment" json:"version_comment"`
|
||||||
|
ParentIds []int32 `db:"parent_ids" json:"parent_ids"`
|
||||||
|
CreatedAt sql.NullTime `db:"created_at" json:"created_at"`
|
||||||
|
UpdatedAt sql.NullTime `db:"updated_at" json:"updated_at"`
|
||||||
|
QuestionsCount sql.NullInt32 `db:"questions_count" json:"questions_count"`
|
||||||
|
AnswersCount sql.NullInt32 `db:"answers_count" json:"answers_count"`
|
||||||
|
AverageTimePassing sql.NullInt32 `db:"average_time_passing" json:"average_time_passing"`
|
||||||
|
SessionsCount sql.NullInt32 `db:"sessions_count" json:"sessions_count"`
|
||||||
|
Gigachat bool `db:"gigachat" json:"gigachat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type QuizPrivilegeUsage struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
QuizID int64 `db:"quiz_id" json:"quiz_id"`
|
||||||
|
PrivilegeID string `db:"privilege_id" json:"privilege_id"`
|
||||||
|
UsedCount int32 `db:"used_count" json:"used_count"`
|
||||||
|
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||||
|
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type QuizUtm struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Quizid int64 `db:"quizid" json:"quizid"`
|
||||||
|
Utm string `db:"utm" json:"utm"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RespondentState struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
TelegramID int32 `db:"telegram_id" json:"telegram_id"`
|
||||||
|
Quizid int32 `db:"quizid" json:"quizid"`
|
||||||
|
State int64 `db:"state" json:"state"`
|
||||||
|
Lang string `db:"lang" json:"lang"`
|
||||||
|
Contact string `db:"contact" json:"contact"`
|
||||||
|
Finish bool `db:"finish" json:"finish"`
|
||||||
|
Session sql.NullString `db:"session" json:"session"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Rule struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Accountid int32 `db:"accountid" json:"accountid"`
|
||||||
|
Quizid int32 `db:"quizid" json:"quizid"`
|
||||||
|
Performerid int32 `db:"performerid" json:"performerid"`
|
||||||
|
Pipelineid int32 `db:"pipelineid" json:"pipelineid"`
|
||||||
|
Stepid int32 `db:"stepid" json:"stepid"`
|
||||||
|
Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat sql.NullTime `db:"createdat" json:"createdat"`
|
||||||
|
Tagstoadd json.RawMessage `db:"tagstoadd" json:"tagstoadd"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Step struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Amoid int32 `db:"amoid" json:"amoid"`
|
||||||
|
Pipelineid int32 `db:"pipelineid" json:"pipelineid"`
|
||||||
|
Accountid int32 `db:"accountid" json:"accountid"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
|
Color string `db:"color" json:"color"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat sql.NullTime `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stepbitrix struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Bitrixid string `db:"bitrixid" json:"bitrixid"`
|
||||||
|
Entityid string `db:"entityid" json:"entityid"`
|
||||||
|
Statusid string `db:"statusid" json:"statusid"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
|
Nameinit string `db:"nameinit" json:"nameinit"`
|
||||||
|
Color string `db:"color" json:"color"`
|
||||||
|
Pipelineid int32 `db:"pipelineid" json:"pipelineid"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat time.Time `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tag struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Amoid int32 `db:"amoid" json:"amoid"`
|
||||||
|
Accountid int32 `db:"accountid" json:"accountid"`
|
||||||
|
Entity interface{} `db:"entity" json:"entity"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
|
Color string `db:"color" json:"color"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat sql.NullTime `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TelegramIntegration struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Quizid int32 `db:"quizid" json:"quizid"`
|
||||||
|
BotToken string `db:"bot_token" json:"bot_token"`
|
||||||
|
BotName string `db:"bot_name" json:"bot_name"`
|
||||||
|
Repeatable sql.NullBool `db:"repeatable" json:"repeatable"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Status interface{} `db:"status" json:"status"`
|
||||||
|
InstanceID int32 `db:"instance_id" json:"instance_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TelegramIntegrationInstance struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Checkout int64 `db:"checkout" json:"checkout"`
|
||||||
|
Limited int32 `db:"limited" json:"limited"`
|
||||||
|
Amount int32 `db:"amount" json:"amount"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TelegramUserQuizResult struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
BotID int64 `db:"bot_id" json:"bot_id"`
|
||||||
|
QuizID int64 `db:"quiz_id" json:"quiz_id"`
|
||||||
|
CurrentField sql.NullString `db:"current_field" json:"current_field"`
|
||||||
|
UserAnswer sql.NullString `db:"user_answer" json:"user_answer"`
|
||||||
|
State interface{} `db:"state" json:"state"`
|
||||||
|
Session string `db:"session" json:"session"`
|
||||||
|
QuestionID int64 `db:"question_id" json:"question_id"`
|
||||||
|
Iter int32 `db:"iter" json:"iter"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tgaccount struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Apiid int32 `db:"apiid" json:"apiid"`
|
||||||
|
Apihash string `db:"apihash" json:"apihash"`
|
||||||
|
Phonenumber string `db:"phonenumber" json:"phonenumber"`
|
||||||
|
Password string `db:"password" json:"password"`
|
||||||
|
Status interface{} `db:"status" json:"status"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat time.Time `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Token struct {
|
||||||
|
Accountid string `db:"accountid" json:"accountid"`
|
||||||
|
Refreshtoken string `db:"refreshtoken" json:"refreshtoken"`
|
||||||
|
Accesstoken string `db:"accesstoken" json:"accesstoken"`
|
||||||
|
Authcode string `db:"authcode" json:"authcode"`
|
||||||
|
Expiration time.Time `db:"expiration" json:"expiration"`
|
||||||
|
Createdat sql.NullTime `db:"createdat" json:"createdat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Usersamo struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
Amoid int32 `db:"amoid" json:"amoid"`
|
||||||
|
Amouserid int32 `db:"amouserid" json:"amouserid"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
|
Email string `db:"email" json:"email"`
|
||||||
|
Role int32 `db:"role" json:"role"`
|
||||||
|
Group int32 `db:"Group" json:"Group"`
|
||||||
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Createdat time.Time `db:"createdat" json:"createdat"`
|
||||||
|
}
|
196
dal/sqlcgen/queries.sql.go
Normal file
196
dal/sqlcgen/queries.sql.go
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// sqlc v1.29.0
|
||||||
|
// source: queries.sql
|
||||||
|
|
||||||
|
package sqlcgen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/lib/pq"
|
||||||
|
)
|
||||||
|
|
||||||
|
const getQuestionListByIDs = `-- name: GetQuestionListByIDs :many
|
||||||
|
SELECT id, quiz_id, title, description, questiontype, required, deleted, page, content, version, parent_ids, created_at, updated_at, session, auditory FROM question WHERE id = ANY($1::int[]) AND deleted = FALSE
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetQuestionListByIDs(ctx context.Context, dollar_1 []int32) ([]Question, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, getQuestionListByIDs, pq.Array(dollar_1))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []Question
|
||||||
|
for rows.Next() {
|
||||||
|
var i Question
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.QuizID,
|
||||||
|
&i.Title,
|
||||||
|
&i.Description,
|
||||||
|
&i.Questiontype,
|
||||||
|
&i.Required,
|
||||||
|
&i.Deleted,
|
||||||
|
&i.Page,
|
||||||
|
&i.Content,
|
||||||
|
&i.Version,
|
||||||
|
pq.Array(&i.ParentIds),
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.UpdatedAt,
|
||||||
|
&i.Session,
|
||||||
|
&i.Auditory,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const insertAnswers = `-- name: InsertAnswers :one
|
||||||
|
INSERT INTO answer(
|
||||||
|
content,
|
||||||
|
quiz_id,
|
||||||
|
question_id,
|
||||||
|
fingerprint,
|
||||||
|
session,
|
||||||
|
result,
|
||||||
|
email,
|
||||||
|
device_type,
|
||||||
|
device,
|
||||||
|
os,
|
||||||
|
browser,
|
||||||
|
ip,
|
||||||
|
start,
|
||||||
|
utm,
|
||||||
|
version
|
||||||
|
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15)
|
||||||
|
RETURNING id, content, quiz_id, question_id, fingerprint, session, created_at, result, new, deleted, email, device_type, device, os, browser, ip, start, utm, version
|
||||||
|
`
|
||||||
|
|
||||||
|
type InsertAnswersParams struct {
|
||||||
|
Content sql.NullString `db:"content" json:"content"`
|
||||||
|
QuizID int64 `db:"quiz_id" json:"quiz_id"`
|
||||||
|
QuestionID int64 `db:"question_id" json:"question_id"`
|
||||||
|
Fingerprint sql.NullString `db:"fingerprint" json:"fingerprint"`
|
||||||
|
Session sql.NullString `db:"session" json:"session"`
|
||||||
|
Result sql.NullBool `db:"result" json:"result"`
|
||||||
|
Email string `db:"email" json:"email"`
|
||||||
|
DeviceType string `db:"device_type" json:"device_type"`
|
||||||
|
Device string `db:"device" json:"device"`
|
||||||
|
Os string `db:"os" json:"os"`
|
||||||
|
Browser string `db:"browser" json:"browser"`
|
||||||
|
Ip string `db:"ip" json:"ip"`
|
||||||
|
Start bool `db:"start" json:"start"`
|
||||||
|
Utm json.RawMessage `db:"utm" json:"utm"`
|
||||||
|
Version int32 `db:"version" json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) InsertAnswers(ctx context.Context, arg InsertAnswersParams) (Answer, error) {
|
||||||
|
row := q.db.QueryRowContext(ctx, insertAnswers,
|
||||||
|
arg.Content,
|
||||||
|
arg.QuizID,
|
||||||
|
arg.QuestionID,
|
||||||
|
arg.Fingerprint,
|
||||||
|
arg.Session,
|
||||||
|
arg.Result,
|
||||||
|
arg.Email,
|
||||||
|
arg.DeviceType,
|
||||||
|
arg.Device,
|
||||||
|
arg.Os,
|
||||||
|
arg.Browser,
|
||||||
|
arg.Ip,
|
||||||
|
arg.Start,
|
||||||
|
arg.Utm,
|
||||||
|
arg.Version,
|
||||||
|
)
|
||||||
|
var i Answer
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.Content,
|
||||||
|
&i.QuizID,
|
||||||
|
&i.QuestionID,
|
||||||
|
&i.Fingerprint,
|
||||||
|
&i.Session,
|
||||||
|
&i.CreatedAt,
|
||||||
|
&i.Result,
|
||||||
|
&i.New,
|
||||||
|
&i.Deleted,
|
||||||
|
&i.Email,
|
||||||
|
&i.DeviceType,
|
||||||
|
&i.Device,
|
||||||
|
&i.Os,
|
||||||
|
&i.Browser,
|
||||||
|
&i.Ip,
|
||||||
|
&i.Start,
|
||||||
|
&i.Utm,
|
||||||
|
&i.Version,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const insertQuestion = `-- name: InsertQuestion :one
|
||||||
|
INSERT INTO question (
|
||||||
|
quiz_id,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
questiontype,
|
||||||
|
required,
|
||||||
|
page,
|
||||||
|
content,
|
||||||
|
parent_ids,
|
||||||
|
updated_at,
|
||||||
|
session,
|
||||||
|
auditory
|
||||||
|
)
|
||||||
|
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11)
|
||||||
|
RETURNING id, created_at, updated_at
|
||||||
|
`
|
||||||
|
|
||||||
|
type InsertQuestionParams struct {
|
||||||
|
QuizID int64 `db:"quiz_id" json:"quiz_id"`
|
||||||
|
Title string `db:"title" json:"title"`
|
||||||
|
Description sql.NullString `db:"description" json:"description"`
|
||||||
|
Questiontype interface{} `db:"questiontype" json:"questiontype"`
|
||||||
|
Required sql.NullBool `db:"required" json:"required"`
|
||||||
|
Page sql.NullInt16 `db:"page" json:"page"`
|
||||||
|
Content sql.NullString `db:"content" json:"content"`
|
||||||
|
ParentIds []int32 `db:"parent_ids" json:"parent_ids"`
|
||||||
|
UpdatedAt sql.NullTime `db:"updated_at" json:"updated_at"`
|
||||||
|
Session string `db:"session" json:"session"`
|
||||||
|
Auditory int64 `db:"auditory" json:"auditory"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type InsertQuestionRow struct {
|
||||||
|
ID int64 `db:"id" json:"id"`
|
||||||
|
CreatedAt sql.NullTime `db:"created_at" json:"created_at"`
|
||||||
|
UpdatedAt sql.NullTime `db:"updated_at" json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) InsertQuestion(ctx context.Context, arg InsertQuestionParams) (InsertQuestionRow, error) {
|
||||||
|
row := q.db.QueryRowContext(ctx, insertQuestion,
|
||||||
|
arg.QuizID,
|
||||||
|
arg.Title,
|
||||||
|
arg.Description,
|
||||||
|
arg.Questiontype,
|
||||||
|
arg.Required,
|
||||||
|
arg.Page,
|
||||||
|
arg.Content,
|
||||||
|
pq.Array(arg.ParentIds),
|
||||||
|
arg.UpdatedAt,
|
||||||
|
arg.Session,
|
||||||
|
arg.Auditory,
|
||||||
|
)
|
||||||
|
var i InsertQuestionRow
|
||||||
|
err := row.Scan(&i.ID, &i.CreatedAt, &i.UpdatedAt)
|
||||||
|
return i, err
|
||||||
|
}
|
31
go.mod
31
go.mod
@ -5,50 +5,27 @@ go 1.23.2
|
|||||||
toolchain go1.23.4
|
toolchain go1.23.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
gitea.pena/PenaSide/common v0.0.0-20250103085335-91ea31fee517
|
github.com/ClickHouse/clickhouse-go v1.5.4
|
||||||
gitea.pena/PenaSide/hlog v0.0.0-20241125221102-a54c29c002a9
|
|
||||||
gitea.pena/PenaSide/trashlog v0.0.0-20250224122049-ddb4d72e9d07
|
|
||||||
gitea.pena/SQuiz/common v0.0.0-20250610213406-ac5c9d667dc7
|
|
||||||
github.com/go-redis/redis/v8 v8.11.5
|
|
||||||
github.com/gofiber/fiber/v2 v2.52.5
|
github.com/gofiber/fiber/v2 v2.52.5
|
||||||
github.com/minio/minio-go/v7 v7.0.81
|
github.com/google/uuid v1.6.0
|
||||||
|
github.com/lib/pq v1.10.9
|
||||||
github.com/rs/xid v1.6.0
|
github.com/rs/xid v1.6.0
|
||||||
github.com/skeris/appInit v1.0.2
|
github.com/skeris/appInit v1.0.2
|
||||||
go.uber.org/zap v1.27.0
|
go.uber.org/zap v1.27.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
gitea.pena/PenaSide/linters-golang v0.0.0-20241207122018-933207374735 // indirect
|
|
||||||
github.com/ClickHouse/clickhouse-go v1.5.4 // indirect
|
|
||||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
|
||||||
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 // indirect
|
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
|
||||||
github.com/go-ini/ini v1.67.0 // indirect
|
|
||||||
github.com/goccy/go-json v0.10.3 // indirect
|
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
|
||||||
github.com/klauspost/compress v1.17.11 // indirect
|
github.com/klauspost/compress v1.17.11 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
|
||||||
github.com/lib/pq v1.10.9 // indirect
|
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
github.com/minio/md5-simd v1.1.2 // indirect
|
|
||||||
github.com/rivo/uniseg v0.2.0 // indirect
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
github.com/tealeg/xlsx v1.0.5 // indirect
|
github.com/stretchr/testify v1.9.0 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasthttp v1.51.0 // indirect
|
github.com/valyala/fasthttp v1.51.0 // indirect
|
||||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||||
go.etcd.io/bbolt v1.3.10 // indirect
|
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/crypto v0.28.0 // indirect
|
|
||||||
golang.org/x/net v0.30.0 // indirect
|
|
||||||
golang.org/x/sys v0.28.0 // indirect
|
golang.org/x/sys v0.28.0 // indirect
|
||||||
golang.org/x/text v0.19.0 // indirect
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 // indirect
|
|
||||||
google.golang.org/grpc v1.64.0 // indirect
|
|
||||||
google.golang.org/protobuf v1.34.2 // indirect
|
|
||||||
)
|
)
|
||||||
|
86
go.sum
86
go.sum
@ -1,17 +1,3 @@
|
|||||||
gitea.pena/PenaSide/common v0.0.0-20250103085335-91ea31fee517 h1:EgBe8VcdPwmxbSzYLndncP+NmR73uYuXxkTeDlEttEE=
|
|
||||||
gitea.pena/PenaSide/common v0.0.0-20250103085335-91ea31fee517/go.mod h1:91EuBCgcqgJ6mG36n2pds8sPwwfaJytLWOzY3h2YFKU=
|
|
||||||
gitea.pena/PenaSide/hlog v0.0.0-20241125221102-a54c29c002a9 h1:tBkXWNIt8icmkMMnq8MA421RWkUy4OZh5P7C3q8uCu4=
|
|
||||||
gitea.pena/PenaSide/hlog v0.0.0-20241125221102-a54c29c002a9/go.mod h1:sanhSL8aEsfcq21P+eItYiAnKAre+B67nGJmDfk2cf0=
|
|
||||||
gitea.pena/PenaSide/linters-golang v0.0.0-20241207122018-933207374735 h1:jDVeUhGBTXBibmW5dmtJg2m2+z5z2Rf6J4G0LpjVoJ0=
|
|
||||||
gitea.pena/PenaSide/linters-golang v0.0.0-20241207122018-933207374735/go.mod h1:gdd+vOT6up9STkEbxa2qESLIMZFjCmRbkcheFQCVgZU=
|
|
||||||
gitea.pena/PenaSide/trashlog v0.0.0-20250224122049-ddb4d72e9d07 h1:bUIUgzXQt16aBqSccI//BaODpRCTIaqlddSepM98QSc=
|
|
||||||
gitea.pena/PenaSide/trashlog v0.0.0-20250224122049-ddb4d72e9d07/go.mod h1:GRfWJerTUlgy82CiYAxE4tVYSVV54zEJJQy17Fx46E4=
|
|
||||||
gitea.pena/SQuiz/common v0.0.0-20250514124515-870e52266ca5 h1:C+iCsGMSUJonOTNNk8wWYOfzZ0Jjw+2IQ5FaEGwRVT0=
|
|
||||||
gitea.pena/SQuiz/common v0.0.0-20250514124515-870e52266ca5/go.mod h1:zCrUwDh0APpztKk6NUqTZv+zhjVbWpGBJiJ5z9dAH0U=
|
|
||||||
gitea.pena/SQuiz/common v0.0.0-20250610192732-9f01faa53ea9 h1:y97VEguCy1Qf/hl/XT9IfX3EgwLgAkn2+1sBDuxjo7Q=
|
|
||||||
gitea.pena/SQuiz/common v0.0.0-20250610192732-9f01faa53ea9/go.mod h1:zCrUwDh0APpztKk6NUqTZv+zhjVbWpGBJiJ5z9dAH0U=
|
|
||||||
gitea.pena/SQuiz/common v0.0.0-20250610213406-ac5c9d667dc7 h1:LdL8G958qTeDNNsLbqhnlnFbbiSMoqqULnNqxIR4c/w=
|
|
||||||
gitea.pena/SQuiz/common v0.0.0-20250610213406-ac5c9d667dc7/go.mod h1:zCrUwDh0APpztKk6NUqTZv+zhjVbWpGBJiJ5z9dAH0U=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/ClickHouse/clickhouse-go v1.5.4 h1:cKjXeYLNWVJIx2J1K6H2CqyRmfwVJVY1OV1coaaFcI0=
|
github.com/ClickHouse/clickhouse-go v1.5.4 h1:cKjXeYLNWVJIx2J1K6H2CqyRmfwVJVY1OV1coaaFcI0=
|
||||||
github.com/ClickHouse/clickhouse-go v1.5.4/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
|
github.com/ClickHouse/clickhouse-go v1.5.4/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
|
||||||
@ -19,38 +5,14 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1
|
|||||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||||
github.com/bkaradzic/go-lz4 v1.0.0 h1:RXc4wYsyz985CkXXeX04y4VnZFGG8Rd43pRaHsOXAKk=
|
github.com/bkaradzic/go-lz4 v1.0.0 h1:RXc4wYsyz985CkXXeX04y4VnZFGG8Rd43pRaHsOXAKk=
|
||||||
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
|
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
|
||||||
github.com/caarlos0/env/v8 v8.0.0 h1:POhxHhSpuxrLMIdvTGARuZqR4Jjm8AYmoi/JKlcScs0=
|
|
||||||
github.com/caarlos0/env/v8 v8.0.0/go.mod h1:7K4wMY9bH0esiXSSHlfHLX5xKGQMnkH5Fk4TDSSSzfo=
|
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
|
||||||
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 h1:F1EaeKL/ta07PY/k9Os/UFtwERei2/XzGemhpGnBKNg=
|
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 h1:F1EaeKL/ta07PY/k9Os/UFtwERei2/XzGemhpGnBKNg=
|
||||||
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
|
||||||
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
|
|
||||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
|
||||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
|
||||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
|
||||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
|
||||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
|
||||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
|
||||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
|
||||||
github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
|
github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
|
||||||
github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
|
github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
@ -58,15 +20,9 @@ github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhB
|
|||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
@ -78,23 +34,9 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
|||||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
|
||||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
|
||||||
github.com/minio/minio-go/v7 v7.0.81 h1:SzhMN0TQ6T/xSBu6Nvw3M5M8voM+Ht8RH3hE8S7zxaA=
|
|
||||||
github.com/minio/minio-go/v7 v7.0.81/go.mod h1:84gmIilaX4zcvAWWzJ5Z1WI5axN+hAbM5w25xf8xvC0=
|
|
||||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
|
||||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
|
||||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
|
||||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
|
||||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
|
||||||
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
|
||||||
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
|
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
|
||||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||||
github.com/pioz/faker v1.7.3 h1:Tez8Emuq0UN+/d6mo3a9m/9ZZ/zdfJk0c5RtRatrceM=
|
|
||||||
github.com/pioz/faker v1.7.3/go.mod h1:xSpay5w/oz1a6+ww0M3vfpe40pSIykeUPeWEc3TvVlc=
|
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
@ -109,18 +51,12 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
|||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
|
|
||||||
github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM=
|
|
||||||
github.com/themakers/bdd v0.0.0-20210316111417-6b1dfe326f33 h1:N9f/Q+2Ssa+yDcbfaoLTYvXmdeyUUxsJKdPUVsjSmiA=
|
|
||||||
github.com/themakers/bdd v0.0.0-20210316111417-6b1dfe326f33/go.mod h1:rpcH99JknBh8seZmlOlUg51gasZH6QH34oXNsIwYT6E=
|
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
|
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
|
||||||
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
|
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
|
||||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||||
go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0=
|
|
||||||
go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ=
|
|
||||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
@ -133,18 +69,12 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
|||||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
|
||||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
|
||||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
|
||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@ -152,31 +82,15 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
|
||||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 h1:9Xyg6I9IWQZhRVfCWjKK+l6kI0jHcPesVlMnT//aHNo=
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
|
||||||
google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
|
|
||||||
google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
|
|
||||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
|
||||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
|
||||||
gopkg.in/tucnak/telebot.v2 v2.5.0 h1:i+NynLo443Vp+Zn3Gv9JBjh3Z/PaiKAQwcnhNI7y6Po=
|
|
||||||
gopkg.in/tucnak/telebot.v2 v2.5.0/go.mod h1:BgaIIx50PSRS9pG59JH+geT82cfvoJU/IaI5TJdN3v8=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
18
healthchecks/healthchecks.go
Normal file
18
healthchecks/healthchecks.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package healthchecks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Liveness(c *fiber.Ctx) error {
|
||||||
|
return c.SendStatus(fiber.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Readiness(err *error) fiber.Handler {
|
||||||
|
return func(c *fiber.Ctx) error {
|
||||||
|
if *err != nil {
|
||||||
|
return c.SendString((*err).Error())
|
||||||
|
}
|
||||||
|
return c.SendStatus(fiber.StatusOK)
|
||||||
|
}
|
||||||
|
}
|
28
middleware/middleware.go
Normal file
28
middleware/middleware.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/rs/xid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ContextKey string
|
||||||
|
|
||||||
|
const (
|
||||||
|
SessionKey = "X-SessionKey"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AnswererChain() fiber.Handler {
|
||||||
|
return func(c *fiber.Ctx) error {
|
||||||
|
session := c.Get(SessionKey)
|
||||||
|
|
||||||
|
if session == "" {
|
||||||
|
session := xid.New().String()
|
||||||
|
c.Set(SessionKey, session)
|
||||||
|
c.Locals(ContextKey(SessionKey), session)
|
||||||
|
} else {
|
||||||
|
c.Locals(ContextKey(SessionKey), session)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Next()
|
||||||
|
}
|
||||||
|
}
|
133
model/model.go
Normal file
133
model/model.go
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
const TypeText = "text"
|
||||||
|
|
||||||
|
type Quiz struct {
|
||||||
|
Id uint64 `json:"id"`
|
||||||
|
Qid string `json:"qid"` // uuid for secure data get and post
|
||||||
|
AccountId string `json:"accountid"` // account that created the quiz
|
||||||
|
|
||||||
|
Deleted bool `json:"deleted"` // fake delete field
|
||||||
|
Archived bool `json:"archived"` // field for archiving quiz
|
||||||
|
|
||||||
|
Fingerprinting bool `json:"fingerprinting"` // field that need for storing device id
|
||||||
|
Repeatable bool `json:"repeatable"` // make it true for allow more than one quiz checkouting
|
||||||
|
NotePrevented bool `json:"note_prevented"` // note answers even if the quiz was aborted
|
||||||
|
MailNotifications bool `json:"mail_notifications"` // set true if you want get an email with every quiz passing
|
||||||
|
UniqueAnswers bool `json:"unique_answers"` // set true if we you mention only last quiz passing
|
||||||
|
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Config string `json:"config"` // serialize json with config for page rules
|
||||||
|
Status string `json:"status"` // status of quiz as enum. see Status const higher
|
||||||
|
Limit uint64 `json:"limit"` // max count of quiz passing
|
||||||
|
DueTo uint64 `json:"due_to"` // time when quiz is end
|
||||||
|
|
||||||
|
TimeOfPassing uint64 `json:"time_of_passing"` // amount of seconds for give all appropriate answers for quiz
|
||||||
|
Pausable bool `json:"pausable"` // true allows to pause the quiz taking
|
||||||
|
|
||||||
|
Version int `json:"version"`
|
||||||
|
VersionComment string `json:"version_comment"`
|
||||||
|
ParentIds []int32 `json:"parent_ids"`
|
||||||
|
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
QuestionsCount uint64 `json:"questions_count"`
|
||||||
|
SessionCount uint64 `json:"session_count"`
|
||||||
|
PassedCount uint64 `json:"passed_count"`
|
||||||
|
AverageTime uint64 `json:"average_time"`
|
||||||
|
|
||||||
|
Super bool `json:"super"`
|
||||||
|
GroupId uint64 `json:"group_id"`
|
||||||
|
|
||||||
|
GigaChat bool `json:"giga_chat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Question struct {
|
||||||
|
Id uint64 `json:"id"`
|
||||||
|
QuizId uint64 `json:"quiz_id"` // relation to quiz table
|
||||||
|
|
||||||
|
Title string `json:"title"` // title of question
|
||||||
|
Description string `json:"description"` // html\text representation of question and question description for answerer
|
||||||
|
Type string `json:"type"` // type field. enum with constants from consts higher
|
||||||
|
|
||||||
|
Required bool `json:"required"` // answerer must answer this question
|
||||||
|
Deleted bool `json:"deleted"` // fake deleting field
|
||||||
|
|
||||||
|
Page int `json:"page"` // set page number for question
|
||||||
|
//serialized json. caption for button type, array of key-value pairs for checkbox and select types,
|
||||||
|
// placeholder and input title for text and file types
|
||||||
|
Content string `json:"content"`
|
||||||
|
|
||||||
|
Version int `json:"version"`
|
||||||
|
//todo check the best choice: question duplication and no statistics about the most unstable question or
|
||||||
|
//low performance of high complexity join-on-array query
|
||||||
|
ParentIds []int32 `json:"parent_ids"`
|
||||||
|
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
Session string `json:"session"`
|
||||||
|
Auditory int64 `json:"auditory"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Answer struct {
|
||||||
|
Id uint64
|
||||||
|
|
||||||
|
Content string `json:"content"` //serialized json. empty for buttons
|
||||||
|
|
||||||
|
QuestionId uint64 `json:"question_id"` // relation for quiz
|
||||||
|
QuizId uint64 // relation for quiz
|
||||||
|
|
||||||
|
Fingerprint string // device Id
|
||||||
|
Session string // xid of session
|
||||||
|
|
||||||
|
Result bool
|
||||||
|
CreatedAt time.Time
|
||||||
|
New bool `json:"new"`
|
||||||
|
Deleted bool
|
||||||
|
Email string
|
||||||
|
|
||||||
|
DeviceType string
|
||||||
|
Device string
|
||||||
|
Browser string
|
||||||
|
IP string
|
||||||
|
OS string
|
||||||
|
Start bool
|
||||||
|
Utm UTMSavingMap
|
||||||
|
Version int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type UTMSavingMap map[string]string
|
||||||
|
|
||||||
|
type ResultContent struct {
|
||||||
|
Text string `json:"text"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
Telegram string `json:"telegram"`
|
||||||
|
Wechat string `json:"wechat"`
|
||||||
|
Viber string `json:"viber"`
|
||||||
|
Vk string `json:"vk"`
|
||||||
|
Skype string `json:"skype"`
|
||||||
|
Whatsup string `json:"whatsup"`
|
||||||
|
Messenger string `json:"messenger"`
|
||||||
|
Custom map[string]string `json:"customs"`
|
||||||
|
Start bool `json:"start"`
|
||||||
|
//IMGContent ImageContent `json:"imagecontent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type QuizConfig struct {
|
||||||
|
Mailing ResultInfo `json:"resultInfo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResultInfo struct {
|
||||||
|
When string `json:"when"` // before|after|email
|
||||||
|
Theme string `json:"theme"` // тема письма
|
||||||
|
Reply string `json:"reply"` // email для ответов, указывается в создании письма
|
||||||
|
ReplName string `json:"repl_name"` // имя отправителя
|
||||||
|
}
|
@ -4,9 +4,9 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"gitea.pena/SQuiz/answerer/clients"
|
"gitea.pena/SQuiz/answerer/clients"
|
||||||
quizdal "gitea.pena/SQuiz/common/dal"
|
quizdal "gitea.pena/SQuiz/answerer/dal"
|
||||||
"gitea.pena/SQuiz/common/middleware"
|
"gitea.pena/SQuiz/answerer/middleware"
|
||||||
"gitea.pena/SQuiz/common/model"
|
"gitea.pena/SQuiz/answerer/model"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -147,7 +147,7 @@ func (s *Service) PutAnswersOnePiece(c *fiber.Ctx) error {
|
|||||||
fp = cfp
|
fp = cfp
|
||||||
}
|
}
|
||||||
|
|
||||||
quiz, err := s.dal.QuizRepo.GetQuizByQid(c.Context(), quizID[0])
|
quiz, err := s.dal.GetQuizByQid(c.Context(), quizID[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(fiber.StatusInternalServerError).SendString("can not get quiz")
|
return c.Status(fiber.StatusInternalServerError).SendString("can not get quiz")
|
||||||
}
|
}
|
||||||
@ -164,7 +164,7 @@ func (s *Service) PutAnswersOnePiece(c *fiber.Ctx) error {
|
|||||||
final = parsedFinal
|
final = parsedFinal
|
||||||
}
|
}
|
||||||
|
|
||||||
question, err := s.dal.QuestionRepo.GetQuestionListByIDs(c.Context(), []int32{int32(ans.QuestionId)})
|
question, err := s.dal.GetQuestionListByIDs(c.Context(), []int32{int32(ans.QuestionId)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(fiber.StatusInternalServerError).SendString("can not get questions")
|
return c.Status(fiber.StatusInternalServerError).SendString("can not get questions")
|
||||||
}
|
}
|
||||||
@ -178,7 +178,7 @@ func (s *Service) PutAnswersOnePiece(c *fiber.Ctx) error {
|
|||||||
return c.Status(fiber.StatusInternalServerError).SendString(fmt.Sprintf("failed send answer to ai, err: %s", err.Error()))
|
return c.Status(fiber.StatusInternalServerError).SendString(fmt.Sprintf("failed send answer to ai, err: %s", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = s.dal.QuestionRepo.CreateQuestion(c.Context(), &model.Question{
|
_, err = s.dal.CreateQuestion(c.Context(), &model.Question{
|
||||||
QuizId: quiz.Id,
|
QuizId: quiz.Id,
|
||||||
Title: truncateUTF8(questionText, 512),
|
Title: truncateUTF8(questionText, 512),
|
||||||
Type: model.TypeText,
|
Type: model.TypeText,
|
||||||
@ -234,7 +234,7 @@ func (s *Service) PutAnswersOnePiece(c *fiber.Ctx) error {
|
|||||||
return c.Status(fiber.StatusInternalServerError).SendString("can not unmarshal quiz config")
|
return c.Status(fiber.StatusInternalServerError).SendString("can not unmarshal quiz config")
|
||||||
}
|
}
|
||||||
|
|
||||||
stored, ers := s.dal.AnswerRepo.CreateAnswers(c.Context(), answers, cs, fp, quiz.Id)
|
stored, ers := s.dal.CreateAnswers(c.Context(), answers, cs, fp, quiz.Id)
|
||||||
if len(ers) != 0 {
|
if len(ers) != 0 {
|
||||||
for _, err := range ers {
|
for _, err := range ers {
|
||||||
if strings.Contains(err.Error(), "duplicate key value") {
|
if strings.Contains(err.Error(), "duplicate key value") {
|
||||||
|
64
sqlc.yaml
Normal file
64
sqlc.yaml
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
version: "1"
|
||||||
|
packages:
|
||||||
|
- name: "sqlcgen"
|
||||||
|
path: "./dal/sqlcgen"
|
||||||
|
queries: "./dal/db_query/queries.sql"
|
||||||
|
schema:
|
||||||
|
- "./dal/schema/000001_init.up.sql"
|
||||||
|
- "./dal/schema/000001_init.down.sql"
|
||||||
|
- "./dal/schema/000002_init.up.sql"
|
||||||
|
- "./dal/schema/000002_init.down.sql"
|
||||||
|
- "./dal/schema/000003_init.up.sql"
|
||||||
|
- "./dal/schema/000003_init.down.sql"
|
||||||
|
- "./dal/schema/000004_init.up.sql"
|
||||||
|
- "./dal/schema/000004_init.down.sql"
|
||||||
|
- "./dal/schema/000005_init.up.sql"
|
||||||
|
- "./dal/schema/000005_init.down.sql"
|
||||||
|
- "./dal/schema/000006_init.up.sql"
|
||||||
|
- "./dal/schema/000006_init.down.sql"
|
||||||
|
- "./dal/schema/000007_init.up.sql"
|
||||||
|
- "./dal/schema/000007_init.down.sql"
|
||||||
|
- "./dal/schema/000008_init.up.sql"
|
||||||
|
- "./dal/schema/000008_init.down.sql"
|
||||||
|
- "./dal/schema/000009_init.up.sql"
|
||||||
|
- "./dal/schema/000009_init.down.sql"
|
||||||
|
- "./dal/schema/000010_init.up.sql"
|
||||||
|
- "./dal/schema/000010_init.down.sql"
|
||||||
|
- "./dal/schema/000011_init.up.sql"
|
||||||
|
- "./dal/schema/000011_init.down.sql"
|
||||||
|
- "./dal/schema/000012_init.up.sql"
|
||||||
|
- "./dal/schema/000012_init.down.sql"
|
||||||
|
- "./dal/schema/000013_init.up.sql"
|
||||||
|
- "./dal/schema/000013_init.down.sql"
|
||||||
|
- "./dal/schema/000014_init.up.sql"
|
||||||
|
- "./dal/schema/000014_init.down.sql"
|
||||||
|
- "./dal/schema/000016_init.up.sql"
|
||||||
|
- "./dal/schema/000016_init.down.sql"
|
||||||
|
- "./dal/schema/000017_init.up.sql"
|
||||||
|
- "./dal/schema/000017_init.down.sql"
|
||||||
|
- "./dal/schema/000018_init.up.sql"
|
||||||
|
- "./dal/schema/000018_init.down.sql"
|
||||||
|
- "./dal/schema/000019_init.up.sql"
|
||||||
|
- "./dal/schema/000019_init.down.sql"
|
||||||
|
- "./dal/schema/000020_init.up.sql"
|
||||||
|
- "./dal/schema/000020_init.down.sql"
|
||||||
|
- "./dal/schema/000021_init.up.sql"
|
||||||
|
- "./dal/schema/000021_init.down.sql"
|
||||||
|
- "./dal/schema/000022_init.up.sql"
|
||||||
|
- "./dal/schema/000022_init.down.sql"
|
||||||
|
- "./dal/schema/000023_init.up.sql"
|
||||||
|
- "./dal/schema/000023_init.down.sql"
|
||||||
|
- "./dal/schema/000024_init.up.sql"
|
||||||
|
- "./dal/schema/000024_init.down.sql"
|
||||||
|
- "./dal/schema/000025_init.up.sql"
|
||||||
|
- "./dal/schema/000025_init.down.sql"
|
||||||
|
- "./dal/schema/000026_init.up.sql"
|
||||||
|
- "./dal/schema/000026_init.down.sql"
|
||||||
|
engine: "postgresql"
|
||||||
|
emit_json_tags: true
|
||||||
|
emit_db_tags: true
|
||||||
|
emit_prepared_queries: false
|
||||||
|
emit_interface: false
|
||||||
|
emit_exact_table_names: false
|
||||||
|
emit_empty_slices: false
|
||||||
|
sql_package: "database/sql"
|
Loading…
Reference in New Issue
Block a user