diff --git a/dal/db_query/queries.sql b/dal/db_query/queries.sql index 16d01c9..78114f7 100644 --- a/dal/db_query/queries.sql +++ b/dal/db_query/queries.sql @@ -32,10 +32,11 @@ INSERT INTO question ( page, content, parent_ids, - updated_at + updated_at, + session ) -VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9) -RETURNING id, created_at, updated_at; +VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10) + RETURNING id, created_at, updated_at; -- name: DeleteQuestion :one UPDATE question SET deleted=true WHERE id=$1 RETURNING question.*; @@ -166,7 +167,7 @@ SELECT * FROM quiz WHERE deleted = false AND archived = false AND - status = 'start' AND + (status = 'start' OR status = 'ai') AND qid = $1; -- name: GetQuestionTitle :one @@ -510,24 +511,25 @@ FROM AND tb.time_interval_end = at.time_interval_end; -- name: QuestionsStatistics :many -WITH Funnel AS ( +WITH QuizAnswers AS ( +SELECT + session, start, result, question_id, created_at, content, quiz_id + FROM answer + WHERE answer.quiz_id = $1 AND created_at between TO_TIMESTAMP($2)::timestamp and TO_TIMESTAMP($3)::timestamp +), QuizQuestions AS (SELECT title, page, id from question where quiz_id = $1), Funnel AS ( SELECT COUNT(DISTINCT a.session) FILTER (WHERE a.start = FALSE) AS count_start_false, COUNT(DISTINCT a.session) FILTER (WHERE a.start = TRUE) AS count_start_true, COUNT(DISTINCT CASE WHEN a.result = FALSE AND qid_true_result IS NOT NULL THEN a.session END) AS count_f_result_with_t_question, COUNT(DISTINCT a.session) FILTER (WHERE a.result = TRUE) AS count_t_result FROM - answer a + QuizAnswers a LEFT JOIN ( SELECT DISTINCT a.session, q.id AS qid_true_result - FROM answer a + FROM QuizAnswers a JOIN question q ON a.question_id = q.id WHERE a.result = TRUE AND a.quiz_id = $1 ) AS q ON a.session = q.session - WHERE - a.quiz_id = $1 - AND a.created_at >= TO_TIMESTAMP($2) - AND a.created_at <= TO_TIMESTAMP($3) ), Results AS ( SELECT @@ -550,16 +552,18 @@ WITH Funnel AS ( LastContent AS ( SELECT a.question_id, - a.content AS last_answer_content + a.content AS last_answer_content, + a.result, + a.start FROM - answer a - JOIN ( + QuizAnswers a + LEFT JOIN ( SELECT session, question_id, MAX(created_at) AS last_created_at FROM - answer + QuizAnswers WHERE quiz_id = $1 AND start != true @@ -734,48 +738,78 @@ SELECT * FROM usersamo WHERE amoid = $1 AND deleted = false; WITH user_data AS ( SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false ) -SELECT u.*, COUNT(*) OVER() as total_count +SELECT u.* FROM usersAmo u JOIN user_data a ON u.AmoID = a.AmoID WHERE u.Deleted = false ORDER BY u.ID OFFSET ($2 - 1) * $3 LIMIT $3; +-- name: GetUsersCount :one +WITH user_data AS ( + SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false +) +SELECT COUNT(*) FROM usersAmo u JOIN user_data a ON u.AmoID = a.AmoID WHERE u.Deleted = false; + -- name: GetTagsWithPagination :many WITH user_data AS ( SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false ) -SELECT t.*, COUNT(*) OVER() as total_count +SELECT t.* FROM tags t JOIN user_data u ON t.AccountID = u.AmoID WHERE t.Deleted = false ORDER BY t.ID OFFSET ($2 - 1) * $3 LIMIT $3; +-- name: GetTagsCount :one +WITH user_data AS ( + SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false +) +SELECT COUNT(*) FROM tags t JOIN user_data u ON t.AccountID = u.AmoID WHERE t.Deleted = false; + -- name: GetStepsWithPagination :many WITH user_data AS ( SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false ) -SELECT s.*, COUNT(*) OVER() as total_count +SELECT s.* FROM steps s JOIN user_data u ON s.AccountID = u.AmoID -WHERE s.Deleted = false AND PipelineID = $4 +WHERE s.Deleted = false AND s.PipelineID = $4 ORDER BY s.ID OFFSET ($2 - 1) * $3 LIMIT $3; +-- name: GetStepsCount :one +WITH user_data AS ( + SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false +) +SELECT COUNT(*) FROM steps s JOIN user_data u ON s.AccountID = u.AmoID WHERE s.Deleted = false AND s.PipelineID = $2; + -- name: GetPipelinesWithPagination :many WITH user_data AS ( SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false ) -SELECT p.*, COUNT(*) OVER() as total_count +SELECT p.* FROM pipelines p JOIN user_data u ON p.AccountID = u.AmoID WHERE p.Deleted = false ORDER BY p.ID OFFSET ($2 - 1) * $3 LIMIT $3; +-- name: GetPipelinesCount :one +WITH user_data AS ( + SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false +) +SELECT COUNT(*) FROM pipelines p JOIN user_data u ON p.AccountID = u.AmoID WHERE p.Deleted = false; + -- name: GetFieldsWithPagination :many WITH user_data AS ( SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false ) -SELECT f.*, COUNT(*) OVER() as total_count +SELECT f.* FROM fields f JOIN user_data u ON f.AccountID = u.AmoID WHERE f.Deleted = false ORDER BY f.ID OFFSET ($2 - 1) * $3 LIMIT $3; +-- name: GetFieldsCount :one +WITH user_data AS ( + SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false +) +SELECT COUNT(*) FROM fields f JOIN user_data u ON f.AccountID = u.AmoID WHERE f.Deleted = false; + -- name: UpdateTags :exec UPDATE tags AS t SET name = (update_data ->> 'Name')::varchar(512), @@ -831,7 +865,7 @@ WITH user_data AS ( CURRENT_TIMESTAMP FROM new_tags nt JOIN user_data ud ON true - ON CONFLICT (amoID, accountID, Entity) DO NOTHING + ON CONFLICT (amoID, accountID, Entity) DO UPDATE SET Deleted = false RETURNING * ) SELECT nt.*,ud.AmoID @@ -884,17 +918,17 @@ WITH user_data AS ( FROM json_array_elements($2::json) AS field ), inserted_fields AS( INSERT INTO fields (amoID, code, accountID, name, Entity, type, createdAt) - SELECT nf.amoID, - nf.code, - ud.AmoID, - nf.name, - nf.Entity, - nf.type, - nf.createdAt - FROM new_fields nf - JOIN user_data ud ON true - ON CONFLICT (amoID, accountID, entity) DO NOTHING - RETURNING * + SELECT nf.amoID, + nf.code, + ud.AmoID, + nf.name, + nf.Entity, + nf.type, + nf.createdAt + FROM new_fields nf + JOIN user_data ud ON true + ON CONFLICT (amoID, accountID, entity) DO UPDATE SET Deleted=false + RETURNING * ) SELECT nf.*,ud.AmoID FROM new_fields nf @@ -939,7 +973,7 @@ WHERE NOT EXISTS ( SELECT * FROM tokens WHERE accountID = $1; -- name: GetQuizRule :one -SELECT * FROM rules WHERE QuizID = $1 AND Deleted = false; +SELECT * FROM rules WHERE QuizID = $1 AND AccountID = (SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $2 AND accountsAmo.Deleted = false) AND Deleted = false; -- name: SetQuizSettings :one INSERT INTO rules (AccountID, QuizID, PerformerID, PipelineID, StepID, FieldsRule,TagsToAdd) @@ -949,8 +983,8 @@ RETURNING id; -- name: ChangeQuizSettings :one UPDATE rules -SET PerformerID = $1,PipelineID = $2,StepID = $3,FieldsRule = $4, TagsToAdd=$5 -WHERE AccountID = (SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $6 AND accountsAmo.Deleted = false) AND QuizID = $7 AND Deleted = false +SET PerformerID = $1,PipelineID = $2,StepID = $3,FieldsRule = $4, TagsToAdd=$5, Deleted = false +WHERE AccountID = (SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $6 AND accountsAmo.Deleted = false) AND QuizID = $7 RETURNING id; -- name: GetQuestionListByIDs :many @@ -970,11 +1004,11 @@ VALUES ($1, $2, $3, $4, $5, $6); -- name: GettingAmoUsersTrueResults :many SELECT a.quiz_id,a.id,a.result,a.question_id,a.content,a.session, - COALESCE((SELECT a2.utm - FROM answer a2 - WHERE a2.start = true AND a2.session = a.session - LIMIT 1), '{}'::jsonb) AS utm - ,t.accesstoken,r.accountid,r.fieldsrule,r.tagstoadd,r.performerid,r.stepid,r.pipelineid,(SELECT u.name FROM usersAmo u WHERE u.AmoUserID = r.performerid AND u.deleted = false) AS performer_name,u.subdomain,u.accountid,u.driveurl + COALESCE((SELECT a2.utm + FROM answer a2 + WHERE a2.start = true AND a2.session = a.session + LIMIT 1), '{}'::jsonb) AS utm +,t.accesstoken,r.accountid,r.fieldsrule,r.tagstoadd,r.performerid,r.stepid,r.pipelineid,(SELECT u.name FROM usersAmo u WHERE u.AmoUserID = r.performerid AND u.amoid = r.accountid AND u.deleted = false) AS performer_name,u.subdomain,u.accountid,u.driveurl FROM answer a INNER JOIN quiz q ON a.quiz_id = q.id LEFT JOIN amoCRMStatuses s ON a.id = s.AnswerID @@ -1057,6 +1091,26 @@ INSERT INTO amoContact (AccountID, AmoID, Field) VALUES ($1, $2, $3) RETURNING A -- name: UpdateAmoContact :exec UPDATE amoContact SET Field = $1,AmoID=$3 WHERE ID = $2; +-- name: GetQuestionsAI :many +SELECT q.id, q.quiz_id, q.title, q.description, q.questiontype, q.required, q.deleted, q.page, q.content, q.version, q.parent_ids, q.created_at, q.updated_at, q.session FROM question q +WHERE q.quiz_id = $1 AND (q.session = $2 OR q.session = '') AND q.deleted = FALSE +ORDER BY (q.session != '') ASC, --без сессии первые потом с сессией + q.page, --по возрастанию страницы + q.created_at --по времени создания + LIMIT $3 OFFSET $4; + +-- name: GetQuestionsAICount :one +SELECT COUNT(*) AS count FROM question WHERE quiz_id = $1 AND (session = $2 OR session = '') AND deleted = FALSE; + +-- name: CreateQuizAudience :one +INSERT INTO gigachatAudience (QuizID, Sex, Age) VALUES ($1, $2, $3) RETURNING ID; + +-- name: GetQuizAudience :many +SELECT * FROM gigachatAudience WHERE QuizID = $1 AND Deleted = FALSE; + + +-- name: DeleteQuizAudience :exec +UPDATE gigachatAudience set Deleted = TRUE WHERE QuizID = $1; -- name: CreateLeadTarget :one INSERT INTO leadtarget (accountID,type,quizID,target,InviteLink) VALUES ($1,$2,$3,$4,$5) RETURNING *; diff --git a/dal/schema/000017_init.down.sql b/dal/schema/000017_init.down.sql index 1fe8abb..c2969e1 100644 --- a/dal/schema/000017_init.down.sql +++ b/dal/schema/000017_init.down.sql @@ -1,3 +1,4 @@ +ALTER table question DROP column session; ALTER TABLE account ADD column email varchar(50) NOT NULL default ''; DO $$ @@ -7,4 +8,4 @@ DO $$ END IF; END $$; -DROP TABLE IF EXISTS leadtarget; \ No newline at end of file +DROP TABLE IF EXISTS leadtarget; diff --git a/dal/schema/000017_init.up.sql b/dal/schema/000017_init.up.sql index 8da2b34..0f5aa5e 100644 --- a/dal/schema/000017_init.up.sql +++ b/dal/schema/000017_init.up.sql @@ -1,3 +1,15 @@ +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 $$ diff --git a/dal/schema/000018_init.down.sql b/dal/schema/000018_init.down.sql index 749dbb0..6186e3f 100644 --- a/dal/schema/000018_init.down.sql +++ b/dal/schema/000018_init.down.sql @@ -1,3 +1,5 @@ +DROP TABLE IF EXISTS gigachatAudience; + DROP TABLE IF EXISTS tgAccounts; DO $$ @@ -7,4 +9,4 @@ DO $$ END IF; END $$; -DROP INDEX IF EXISTS idx_apiid_apihash; \ No newline at end of file +DROP INDEX IF EXISTS idx_apiid_apihash; diff --git a/dal/schema/000018_init.up.sql b/dal/schema/000018_init.up.sql index e165366..d6cf7fa 100644 --- a/dal/schema/000018_init.up.sql +++ b/dal/schema/000018_init.up.sql @@ -1,3 +1,13 @@ +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 diff --git a/dal/sqlcgen/models.go b/dal/sqlcgen/models.go index 5d485b5..63e0bbb 100644 --- a/dal/sqlcgen/models.go +++ b/dal/sqlcgen/models.go @@ -159,6 +159,14 @@ type Field struct { Createdat sql.NullTime `db:"createdat" json:"createdat"` } +type Gigachataudience struct { + ID int64 `db:"id" json:"id"` + Quizid int64 `db:"quizid" json:"quizid"` + Sex bool `db:"sex" json:"sex"` + Age string `db:"age" json:"age"` + Deleted bool `db:"deleted" json:"deleted"` + Createdat sql.NullTime `db:"createdat" json:"createdat"` +} type Leadtarget struct { ID int64 `db:"id" json:"id"` Accountid string `db:"accountid" json:"accountid"` @@ -213,6 +221,7 @@ type Question struct { 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"` } type Quiz struct { diff --git a/dal/sqlcgen/queries.sql.go b/dal/sqlcgen/queries.sql.go index f7fd55a..ceab764 100644 --- a/dal/sqlcgen/queries.sql.go +++ b/dal/sqlcgen/queries.sql.go @@ -207,8 +207,8 @@ func (q *Queries) ChangeBitrixQuizSettings(ctx context.Context, arg ChangeBitrix const changeQuizSettings = `-- name: ChangeQuizSettings :one UPDATE rules -SET PerformerID = $1,PipelineID = $2,StepID = $3,FieldsRule = $4, TagsToAdd=$5 -WHERE AccountID = (SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $6 AND accountsAmo.Deleted = false) AND QuizID = $7 AND Deleted = false +SET PerformerID = $1,PipelineID = $2,StepID = $3,FieldsRule = $4, TagsToAdd=$5, Deleted = false +WHERE AccountID = (SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $6 AND accountsAmo.Deleted = false) AND QuizID = $7 RETURNING id ` @@ -537,17 +537,17 @@ WITH user_data AS ( FROM json_array_elements($2::json) AS field ), inserted_fields AS( INSERT INTO fields (amoID, code, accountID, name, Entity, type, createdAt) - SELECT nf.amoID, - nf.code, - ud.AmoID, - nf.name, - nf.Entity, - nf.type, - nf.createdAt - FROM new_fields nf - JOIN user_data ud ON true - ON CONFLICT (amoID, accountID, entity) DO NOTHING - RETURNING id, amoid, code, accountid, name, entity, type, deleted, createdat + SELECT nf.amoID, + nf.code, + ud.AmoID, + nf.name, + nf.Entity, + nf.type, + nf.createdAt + FROM new_fields nf + JOIN user_data ud ON true + ON CONFLICT (amoID, accountID, entity) DO UPDATE SET Deleted=false + RETURNING id, amoid, code, accountid, name, entity, type, deleted, createdat ) SELECT nf.amoid, nf.code, nf.name, nf.entity, nf.type, nf.createdat,ud.AmoID FROM new_fields nf @@ -854,7 +854,7 @@ WITH user_data AS ( CURRENT_TIMESTAMP FROM new_tags nt JOIN user_data ud ON true - ON CONFLICT (amoID, accountID, Entity) DO NOTHING + ON CONFLICT (amoID, accountID, Entity) DO UPDATE SET Deleted = false RETURNING id, amoid, accountid, entity, name, color, deleted, createdat ) SELECT nt.amoid, nt.entity, nt.name, nt.color,ud.AmoID @@ -1078,6 +1078,7 @@ func (q *Queries) CreateAmoAccount(ctx context.Context, arg CreateAmoAccountPara return err } + const createBitrixAccount = `-- name: CreateBitrixAccount :exec INSERT INTO BitrixAccounts (AccountID, BitrixID, Subdomain) VALUES ($1, $2, $3) @@ -1099,6 +1100,10 @@ INSERT INTO BitrixTokens (AccountID, RefreshToken, AccessToken, AuthCode, Expira VALUES ($1, $2, $3, $4, $5, $6) ` +const createQuizAudience = `-- name: CreateQuizAudience :one +INSERT INTO gigachatAudience (QuizID, Sex, Age) VALUES ($1, $2, $3) RETURNING ID +` + type CreateBitrixWebHookParams struct { Accountid string `db:"accountid" json:"accountid"` Refreshtoken string `db:"refreshtoken" json:"refreshtoken"` @@ -1322,7 +1327,7 @@ func (q *Queries) DeletePrivilegeByID(ctx context.Context, id int32) error { } const deleteQuestion = `-- name: DeleteQuestion :one -UPDATE question SET deleted=true WHERE id=$1 RETURNING question.id, question.quiz_id, question.title, question.description, question.questiontype, question.required, question.deleted, question.page, question.content, question.version, question.parent_ids, question.created_at, question.updated_at +UPDATE question SET deleted=true WHERE id=$1 RETURNING question.id, question.quiz_id, question.title, question.description, question.questiontype, question.required, question.deleted, question.page, question.content, question.version, question.parent_ids, question.created_at, question.updated_at, question.session ` func (q *Queries) DeleteQuestion(ctx context.Context, id int64) (Question, error) { @@ -1342,10 +1347,20 @@ func (q *Queries) DeleteQuestion(ctx context.Context, id int64) (Question, error pq.Array(&i.ParentIds), &i.CreatedAt, &i.UpdatedAt, + &i.Session, ) return i, err } +const deleteQuizAudience = `-- name: DeleteQuizAudience :exec +UPDATE gigachatAudience set Deleted = TRUE WHERE QuizID = $1 +` + +func (q *Queries) DeleteQuizAudience(ctx context.Context, quizid int64) error { + _, err := q.db.ExecContext(ctx, deleteQuizAudience, quizid) + return err +} + const deleteQuizByID = `-- name: DeleteQuizByID :one UPDATE quiz SET deleted=true WHERE quiz.id=$1 AND accountid=$2 RETURNING quiz.id, quiz.qid, quiz.accountid, quiz.deleted, quiz.archived, quiz.fingerprinting, quiz.repeatable, quiz.note_prevented, quiz.mail_notifications, quiz.unique_answers, quiz.super, quiz.group_id, quiz.name, quiz.description, quiz.config, quiz.status, quiz.limit_answers, quiz.due_to, quiz.time_of_passing, quiz.pausable, quiz.version, quiz.version_comment, quiz.parent_ids, quiz.created_at, quiz.updated_at, quiz.questions_count, quiz.answers_count, quiz.average_time_passing, quiz.sessions_count ` @@ -2493,11 +2508,25 @@ func (q *Queries) GetFieldByAmoID(ctx context.Context, amoid int32) (Field, erro return i, err } +const getFieldsCount = `-- name: GetFieldsCount :one +WITH user_data AS ( + SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false +) +SELECT COUNT(*) FROM fields f JOIN user_data u ON f.AccountID = u.AmoID WHERE f.Deleted = false +` + +func (q *Queries) GetFieldsCount(ctx context.Context, accountid string) (int64, error) { + row := q.db.QueryRowContext(ctx, getFieldsCount, accountid) + var count int64 + err := row.Scan(&count) + return count, err +} + const getFieldsWithPagination = `-- name: GetFieldsWithPagination :many WITH user_data AS ( SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false ) -SELECT f.id, f.amoid, f.code, f.accountid, f.name, f.entity, f.type, f.deleted, f.createdat, COUNT(*) OVER() as total_count +SELECT f.id, f.amoid, f.code, f.accountid, f.name, f.entity, f.type, f.deleted, f.createdat FROM fields f JOIN user_data u ON f.AccountID = u.AmoID WHERE f.Deleted = false ORDER BY f.ID OFFSET ($2 - 1) * $3 LIMIT $3 @@ -2509,28 +2538,15 @@ type GetFieldsWithPaginationParams struct { Limit int32 `db:"limit" json:"limit"` } -type GetFieldsWithPaginationRow 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"` - TotalCount int64 `db:"total_count" json:"total_count"` -} - -func (q *Queries) GetFieldsWithPagination(ctx context.Context, arg GetFieldsWithPaginationParams) ([]GetFieldsWithPaginationRow, error) { +func (q *Queries) GetFieldsWithPagination(ctx context.Context, arg GetFieldsWithPaginationParams) ([]Field, error) { rows, err := q.db.QueryContext(ctx, getFieldsWithPagination, arg.Accountid, arg.Column2, arg.Limit) if err != nil { return nil, err } defer rows.Close() - var items []GetFieldsWithPaginationRow + var items []Field for rows.Next() { - var i GetFieldsWithPaginationRow + var i Field if err := rows.Scan( &i.ID, &i.Amoid, @@ -2541,7 +2557,6 @@ func (q *Queries) GetFieldsWithPagination(ctx context.Context, arg GetFieldsWith &i.Type, &i.Deleted, &i.Createdat, - &i.TotalCount, ); err != nil { return nil, err } @@ -2653,11 +2668,25 @@ func (q *Queries) GetListStartQuiz(ctx context.Context, accountid string) ([]int return items, nil } +const getPipelinesCount = `-- name: GetPipelinesCount :one +WITH user_data AS ( + SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false +) +SELECT COUNT(*) FROM pipelines p JOIN user_data u ON p.AccountID = u.AmoID WHERE p.Deleted = false +` + +func (q *Queries) GetPipelinesCount(ctx context.Context, accountid string) (int64, error) { + row := q.db.QueryRowContext(ctx, getPipelinesCount, accountid) + var count int64 + err := row.Scan(&count) + return count, err +} + const getPipelinesWithPagination = `-- name: GetPipelinesWithPagination :many WITH user_data AS ( SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false ) -SELECT p.id, p.amoid, p.accountid, p.name, p.isarchive, p.deleted, p.createdat, COUNT(*) OVER() as total_count +SELECT p.id, p.amoid, p.accountid, p.name, p.isarchive, p.deleted, p.createdat FROM pipelines p JOIN user_data u ON p.AccountID = u.AmoID WHERE p.Deleted = false ORDER BY p.ID OFFSET ($2 - 1) * $3 LIMIT $3 @@ -2669,26 +2698,15 @@ type GetPipelinesWithPaginationParams struct { Limit int32 `db:"limit" json:"limit"` } -type GetPipelinesWithPaginationRow 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"` - TotalCount int64 `db:"total_count" json:"total_count"` -} - -func (q *Queries) GetPipelinesWithPagination(ctx context.Context, arg GetPipelinesWithPaginationParams) ([]GetPipelinesWithPaginationRow, error) { +func (q *Queries) GetPipelinesWithPagination(ctx context.Context, arg GetPipelinesWithPaginationParams) ([]Pipeline, error) { rows, err := q.db.QueryContext(ctx, getPipelinesWithPagination, arg.Accountid, arg.Column2, arg.Limit) if err != nil { return nil, err } defer rows.Close() - var items []GetPipelinesWithPaginationRow + var items []Pipeline for rows.Next() { - var i GetPipelinesWithPaginationRow + var i Pipeline if err := rows.Scan( &i.ID, &i.Amoid, @@ -2697,7 +2715,6 @@ func (q *Queries) GetPipelinesWithPagination(ctx context.Context, arg GetPipelin &i.Isarchive, &i.Deleted, &i.Createdat, - &i.TotalCount, ); err != nil { return nil, err } @@ -2861,7 +2878,7 @@ func (q *Queries) GetQidOwner(ctx context.Context, qid uuid.NullUUID) (string, e } const getQuestionHistory = `-- name: GetQuestionHistory :many -SELECT id, quiz_id, title, description, questiontype, required, deleted, page, content, version, parent_ids, created_at, updated_at FROM question WHERE question.id = $1 OR question.id = ANY( +SELECT id, quiz_id, title, description, questiontype, required, deleted, page, content, version, parent_ids, created_at, updated_at, session FROM question WHERE question.id = $1 OR question.id = ANY( SELECT unnest(parent_ids) FROM question WHERE id = $1 ) ORDER BY question.id DESC LIMIT $2 OFFSET $3 ` @@ -2895,6 +2912,7 @@ func (q *Queries) GetQuestionHistory(ctx context.Context, arg GetQuestionHistory pq.Array(&i.ParentIds), &i.CreatedAt, &i.UpdatedAt, + &i.Session, ); err != nil { return nil, err } @@ -2910,7 +2928,7 @@ func (q *Queries) GetQuestionHistory(ctx context.Context, arg GetQuestionHistory } const getQuestionListByIDs = `-- name: GetQuestionListByIDs :many -SELECT id, quiz_id, title, description, questiontype, required, deleted, page, content, version, parent_ids, created_at, updated_at FROM question WHERE id = ANY($1::int[]) AND deleted = FALSE +SELECT id, quiz_id, title, description, questiontype, required, deleted, page, content, version, parent_ids, created_at, updated_at, session FROM question WHERE id = ANY($1::int[]) AND deleted = FALSE ` func (q *Queries) GetQuestionListByIDs(ctx context.Context, dollar_1 []int32) ([]Question, error) { @@ -2936,6 +2954,7 @@ func (q *Queries) GetQuestionListByIDs(ctx context.Context, dollar_1 []int32) ([ pq.Array(&i.ParentIds), &i.CreatedAt, &i.UpdatedAt, + &i.Session, ); err != nil { return nil, err } @@ -2971,12 +2990,86 @@ const getQuestions = `-- name: GetQuestions :many SELECT id, quiz_id, title, description, questiontype, required, deleted, page, content, version, parent_ids, created_at, updated_at FROM question WHERE quiz_id = $1 AND deleted = FALSE ORDER BY page ASC ` -func (q *Queries) GetQuestions(ctx context.Context, quizID int64) ([]Question, error) { +type GetQuestionsRow 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"` +} + +func (q *Queries) GetQuestions(ctx context.Context, quizID int64) ([]GetQuestionsRow, error) { rows, err := q.db.QueryContext(ctx, getQuestions, quizID) if err != nil { return nil, err } defer rows.Close() + var items []GetQuestionsRow + for rows.Next() { + var i GetQuestionsRow + 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, + ); 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 getQuestionsAI = `-- name: GetQuestionsAI :many +SELECT q.id, q.quiz_id, q.title, q.description, q.questiontype, q.required, q.deleted, q.page, q.content, q.version, q.parent_ids, q.created_at, q.updated_at, q.session FROM question q +WHERE q.quiz_id = $1 AND (q.session = $2 OR q.session = '') AND q.deleted = FALSE +ORDER BY (q.session != '') ASC, --без сессии первые потом с сессией + q.page, --по возрастанию страницы + q.created_at --по времени создания + LIMIT $3 OFFSET $4 +` + +type GetQuestionsAIParams struct { + QuizID int64 `db:"quiz_id" json:"quiz_id"` + Session string `db:"session" json:"session"` + Limit int32 `db:"limit" json:"limit"` + Offset int32 `db:"offset" json:"offset"` +} + +func (q *Queries) GetQuestionsAI(ctx context.Context, arg GetQuestionsAIParams) ([]Question, error) { + rows, err := q.db.QueryContext(ctx, getQuestionsAI, + arg.QuizID, + arg.Session, + arg.Limit, + arg.Offset, + ) + if err != nil { + return nil, err + } + defer rows.Close() var items []Question for rows.Next() { var i Question @@ -2994,6 +3087,57 @@ func (q *Queries) GetQuestions(ctx context.Context, quizID int64) ([]Question, e pq.Array(&i.ParentIds), &i.CreatedAt, &i.UpdatedAt, + &i.Session, + ); 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 getQuestionsAICount = `-- name: GetQuestionsAICount :one +SELECT COUNT(*) AS count FROM question WHERE quiz_id = $1 AND (session = $2 OR session = '') AND deleted = FALSE +` + +type GetQuestionsAICountParams struct { + QuizID int64 `db:"quiz_id" json:"quiz_id"` + Session string `db:"session" json:"session"` +} + +func (q *Queries) GetQuestionsAICount(ctx context.Context, arg GetQuestionsAICountParams) (int64, error) { + row := q.db.QueryRowContext(ctx, getQuestionsAICount, arg.QuizID, arg.Session) + var count int64 + err := row.Scan(&count) + return count, err +} + +const getQuizAudience = `-- name: GetQuizAudience :many +SELECT id, quizid, sex, age, deleted, createdat FROM gigachatAudience WHERE QuizID = $1 AND Deleted = FALSE +` + +func (q *Queries) GetQuizAudience(ctx context.Context, quizid int64) ([]Gigachataudience, error) { + rows, err := q.db.QueryContext(ctx, getQuizAudience, quizid) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Gigachataudience + for rows.Next() { + var i Gigachataudience + if err := rows.Scan( + &i.ID, + &i.Quizid, + &i.Sex, + &i.Age, + &i.Deleted, + &i.Createdat, ); err != nil { return nil, err } @@ -3059,7 +3203,7 @@ SELECT id, qid, accountid, deleted, archived, fingerprinting, repeatable, note_p WHERE deleted = false AND archived = false AND - status = 'start' AND + (status = 'start' OR status = 'ai') AND qid = $1 ` @@ -3188,11 +3332,16 @@ func (q *Queries) GetQuizHistory(ctx context.Context, arg GetQuizHistoryParams) } const getQuizRule = `-- name: GetQuizRule :one -SELECT id, accountid, quizid, performerid, pipelineid, stepid, fieldsrule, deleted, createdat, tagstoadd FROM rules WHERE QuizID = $1 AND Deleted = false +SELECT id, accountid, quizid, performerid, pipelineid, stepid, fieldsrule, deleted, createdat, tagstoadd FROM rules WHERE QuizID = $1 AND AccountID = (SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $2 AND accountsAmo.Deleted = false) AND Deleted = false ` -func (q *Queries) GetQuizRule(ctx context.Context, quizid int32) (Rule, error) { - row := q.db.QueryRowContext(ctx, getQuizRule, quizid) +type GetQuizRuleParams struct { + Quizid int32 `db:"quizid" json:"quizid"` + Accountid string `db:"accountid" json:"accountid"` +} + +func (q *Queries) GetQuizRule(ctx context.Context, arg GetQuizRuleParams) (Rule, error) { + row := q.db.QueryRowContext(ctx, getQuizRule, arg.Quizid, arg.Accountid) var i Rule err := row.Scan( &i.ID, @@ -3273,13 +3422,32 @@ func (q *Queries) GetResultAnswers(ctx context.Context, id int64) ([]GetResultAn return items, nil } +const getStepsCount = `-- name: GetStepsCount :one +WITH user_data AS ( + SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false +) +SELECT COUNT(*) FROM steps s JOIN user_data u ON s.AccountID = u.AmoID WHERE s.Deleted = false AND s.PipelineID = $2 +` + +type GetStepsCountParams struct { + Accountid string `db:"accountid" json:"accountid"` + Pipelineid int32 `db:"pipelineid" json:"pipelineid"` +} + +func (q *Queries) GetStepsCount(ctx context.Context, arg GetStepsCountParams) (int64, error) { + row := q.db.QueryRowContext(ctx, getStepsCount, arg.Accountid, arg.Pipelineid) + var count int64 + err := row.Scan(&count) + return count, err +} + const getStepsWithPagination = `-- name: GetStepsWithPagination :many WITH user_data AS ( SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false ) -SELECT s.id, s.amoid, s.pipelineid, s.accountid, s.name, s.color, s.deleted, s.createdat, COUNT(*) OVER() as total_count +SELECT s.id, s.amoid, s.pipelineid, s.accountid, s.name, s.color, s.deleted, s.createdat FROM steps s JOIN user_data u ON s.AccountID = u.AmoID -WHERE s.Deleted = false AND PipelineID = $4 +WHERE s.Deleted = false AND s.PipelineID = $4 ORDER BY s.ID OFFSET ($2 - 1) * $3 LIMIT $3 ` @@ -3290,19 +3458,7 @@ type GetStepsWithPaginationParams struct { Pipelineid int32 `db:"pipelineid" json:"pipelineid"` } -type GetStepsWithPaginationRow 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"` - TotalCount int64 `db:"total_count" json:"total_count"` -} - -func (q *Queries) GetStepsWithPagination(ctx context.Context, arg GetStepsWithPaginationParams) ([]GetStepsWithPaginationRow, error) { +func (q *Queries) GetStepsWithPagination(ctx context.Context, arg GetStepsWithPaginationParams) ([]Step, error) { rows, err := q.db.QueryContext(ctx, getStepsWithPagination, arg.Accountid, arg.Column2, @@ -3313,9 +3469,9 @@ func (q *Queries) GetStepsWithPagination(ctx context.Context, arg GetStepsWithPa return nil, err } defer rows.Close() - var items []GetStepsWithPaginationRow + var items []Step for rows.Next() { - var i GetStepsWithPaginationRow + var i Step if err := rows.Scan( &i.ID, &i.Amoid, @@ -3325,7 +3481,6 @@ func (q *Queries) GetStepsWithPagination(ctx context.Context, arg GetStepsWithPa &i.Color, &i.Deleted, &i.Createdat, - &i.TotalCount, ); err != nil { return nil, err } @@ -3340,11 +3495,25 @@ func (q *Queries) GetStepsWithPagination(ctx context.Context, arg GetStepsWithPa return items, nil } +const getTagsCount = `-- name: GetTagsCount :one +WITH user_data AS ( + SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false +) +SELECT COUNT(*) FROM tags t JOIN user_data u ON t.AccountID = u.AmoID WHERE t.Deleted = false +` + +func (q *Queries) GetTagsCount(ctx context.Context, accountid string) (int64, error) { + row := q.db.QueryRowContext(ctx, getTagsCount, accountid) + var count int64 + err := row.Scan(&count) + return count, err +} + const getTagsWithPagination = `-- name: GetTagsWithPagination :many WITH user_data AS ( SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false ) -SELECT t.id, t.amoid, t.accountid, t.entity, t.name, t.color, t.deleted, t.createdat, COUNT(*) OVER() as total_count +SELECT t.id, t.amoid, t.accountid, t.entity, t.name, t.color, t.deleted, t.createdat FROM tags t JOIN user_data u ON t.AccountID = u.AmoID WHERE t.Deleted = false ORDER BY t.ID OFFSET ($2 - 1) * $3 LIMIT $3 @@ -3356,27 +3525,15 @@ type GetTagsWithPaginationParams struct { Limit int32 `db:"limit" json:"limit"` } -type GetTagsWithPaginationRow 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"` - TotalCount int64 `db:"total_count" json:"total_count"` -} - -func (q *Queries) GetTagsWithPagination(ctx context.Context, arg GetTagsWithPaginationParams) ([]GetTagsWithPaginationRow, error) { +func (q *Queries) GetTagsWithPagination(ctx context.Context, arg GetTagsWithPaginationParams) ([]Tag, error) { rows, err := q.db.QueryContext(ctx, getTagsWithPagination, arg.Accountid, arg.Column2, arg.Limit) if err != nil { return nil, err } defer rows.Close() - var items []GetTagsWithPaginationRow + var items []Tag for rows.Next() { - var i GetTagsWithPaginationRow + var i Tag if err := rows.Scan( &i.ID, &i.Amoid, @@ -3386,7 +3543,6 @@ func (q *Queries) GetTagsWithPagination(ctx context.Context, arg GetTagsWithPagi &i.Color, &i.Deleted, &i.Createdat, - &i.TotalCount, ); err != nil { return nil, err } @@ -3747,6 +3903,19 @@ func (q *Queries) GetUserUsersByID(ctx context.Context, amoid int32) ([]Usersamo return items, nil } +const getUsersCount = `-- name: GetUsersCount :one +WITH user_data AS ( + SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false +) +SELECT COUNT(*) FROM usersAmo u JOIN user_data a ON u.AmoID = a.AmoID WHERE u.Deleted = false +` + +func (q *Queries) GetUsersCount(ctx context.Context, accountid string) (int64, error) { + row := q.db.QueryRowContext(ctx, getUsersCount, accountid) + var count int64 + err := row.Scan(&count) + return count, err +} const getUserUsersByIDBitrix = `-- name: GetUserUsersByIDBitrix :many SELECT id, accountid, bitrixiduserid, name, lastname, secondname, title, email, ufdepartment, workposition, deleted, createdat FROM BitrixAccountUsers WHERE accountID = $1 AND Deleted = false ` @@ -3859,11 +4028,12 @@ func (q *Queries) GetUsersBitrixWithPagination(ctx context.Context, arg GetUsers return items, nil } + const getUsersWithPagination = `-- name: GetUsersWithPagination :many WITH user_data AS ( SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false ) -SELECT u.id, u.amoid, u.amouserid, u.name, u.email, u.role, u."Group", u.deleted, u.createdat, COUNT(*) OVER() as total_count +SELECT u.id, u.amoid, u.amouserid, u.name, u.email, u.role, u."Group", u.deleted, u.createdat FROM usersAmo u JOIN user_data a ON u.AmoID = a.AmoID WHERE u.Deleted = false @@ -3876,20 +4046,7 @@ type GetUsersWithPaginationParams struct { Limit int32 `db:"limit" json:"limit"` } -type GetUsersWithPaginationRow 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"` - TotalCount int64 `db:"total_count" json:"total_count"` -} - -func (q *Queries) GetUsersWithPagination(ctx context.Context, arg GetUsersWithPaginationParams) ([]GetUsersWithPaginationRow, error) { +func (q *Queries) GetUsersWithPagination(ctx context.Context, arg GetUsersWithPaginationParams) ([]Usersamo, error) { rows, err := q.db.QueryContext(ctx, getUsersWithPagination, arg.Accountid, arg.Column2, arg.Limit) if err != nil { return nil, err @@ -3899,6 +4056,7 @@ func (q *Queries) GetUsersWithPagination(ctx context.Context, arg GetUsersWithPa for rows.Next() { var i GetUsersWithPaginationRow if err := rows.Scan( + &i.QuizID, &i.ID, &i.Amoid, &i.Amouserid, @@ -3925,11 +4083,11 @@ func (q *Queries) GetUsersWithPagination(ctx context.Context, arg GetUsersWithPa const gettingAmoUsersTrueResults = `-- name: GettingAmoUsersTrueResults :many SELECT a.quiz_id,a.id,a.result,a.question_id,a.content,a.session, - COALESCE((SELECT a2.utm - FROM answer a2 - WHERE a2.start = true AND a2.session = a.session - LIMIT 1), '{}'::jsonb) AS utm - ,t.accesstoken,r.accountid,r.fieldsrule,r.tagstoadd,r.performerid,r.stepid,r.pipelineid,(SELECT u.name FROM usersAmo u WHERE u.AmoUserID = r.performerid AND u.deleted = false) AS performer_name,u.subdomain,u.accountid,u.driveurl + COALESCE((SELECT a2.utm + FROM answer a2 + WHERE a2.start = true AND a2.session = a.session + LIMIT 1), '{}'::jsonb) AS utm +,t.accesstoken,r.accountid,r.fieldsrule,r.tagstoadd,r.performerid,r.stepid,r.pipelineid,(SELECT u.name FROM usersAmo u WHERE u.AmoUserID = r.performerid AND u.amoid = r.accountid AND u.deleted = false) AS performer_name,u.subdomain,u.accountid,u.driveurl FROM answer a INNER JOIN quiz q ON a.quiz_id = q.id LEFT JOIN amoCRMStatuses s ON a.id = s.AnswerID @@ -4246,10 +4404,11 @@ INSERT INTO question ( page, content, parent_ids, - updated_at + updated_at, + session ) -VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9) -RETURNING id, created_at, updated_at +VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10) + RETURNING id, created_at, updated_at ` type InsertQuestionParams struct { @@ -4262,6 +4421,7 @@ type InsertQuestionParams struct { 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"` } type InsertQuestionRow struct { @@ -4281,6 +4441,7 @@ func (q *Queries) InsertQuestion(ctx context.Context, arg InsertQuestionParams) arg.Content, pq.Array(arg.ParentIds), arg.UpdatedAt, + arg.Session, ) var i InsertQuestionRow err := row.Scan(&i.ID, &i.CreatedAt, &i.UpdatedAt) @@ -4427,24 +4588,25 @@ func (q *Queries) MoveToHistoryQuiz(ctx context.Context, arg MoveToHistoryQuizPa } const questionsStatistics = `-- name: QuestionsStatistics :many -WITH Funnel AS ( +WITH QuizAnswers AS ( +SELECT + session, start, result, question_id, created_at, content, quiz_id + FROM answer + WHERE answer.quiz_id = $1 AND created_at between TO_TIMESTAMP($2)::timestamp and TO_TIMESTAMP($3)::timestamp +), QuizQuestions AS (SELECT title, page, id from question where quiz_id = $1), Funnel AS ( SELECT COUNT(DISTINCT a.session) FILTER (WHERE a.start = FALSE) AS count_start_false, COUNT(DISTINCT a.session) FILTER (WHERE a.start = TRUE) AS count_start_true, COUNT(DISTINCT CASE WHEN a.result = FALSE AND qid_true_result IS NOT NULL THEN a.session END) AS count_f_result_with_t_question, COUNT(DISTINCT a.session) FILTER (WHERE a.result = TRUE) AS count_t_result FROM - answer a + QuizAnswers a LEFT JOIN ( SELECT DISTINCT a.session, q.id AS qid_true_result - FROM answer a + FROM QuizAnswers a JOIN question q ON a.question_id = q.id WHERE a.result = TRUE AND a.quiz_id = $1 ) AS q ON a.session = q.session - WHERE - a.quiz_id = $1 - AND a.created_at >= TO_TIMESTAMP($2) - AND a.created_at <= TO_TIMESTAMP($3) ), Results AS ( SELECT @@ -4453,30 +4615,32 @@ WITH Funnel AS ( CAST(COUNT(*) * 100.0 / NULLIF(SUM(COUNT(*)) FILTER (WHERE a.result = TRUE) OVER (PARTITION BY a.quiz_id), 0) AS FLOAT8) AS percentage FROM question q - JOIN answer a ON q.id = a.question_id + LEFT JOIN QuizAnswers a ON q.id = a.question_id WHERE a.quiz_id = $1 AND a.created_at >= TO_TIMESTAMP($2) AND a.created_at <= TO_TIMESTAMP($3) AND a.result = TRUE GROUP BY - q.title, a.quiz_id, a.result + q.title, a.result, a.quiz_id HAVING COUNT(*) >= 1 ), LastContent AS ( SELECT a.question_id, - a.content AS last_answer_content + a.content AS last_answer_content, + a.result, + a.start FROM - answer a - JOIN ( + QuizAnswers a + LEFT JOIN ( SELECT session, question_id, MAX(created_at) AS last_created_at FROM - answer + QuizAnswers WHERE quiz_id = $1 AND start != true @@ -4484,7 +4648,9 @@ WITH Funnel AS ( AND created_at <= TO_TIMESTAMP($3) GROUP BY question_id, session - ) AS last_created_at_one_session ON a.session = last_created_at_one_session.session AND a.question_id = last_created_at_one_session.question_id AND a.created_at = last_created_at_one_session.last_created_at + ) AS last_created_at_one_session ON a.session = last_created_at_one_session.session + AND a.question_id = last_created_at_one_session.question_id + AND a.created_at = last_created_at_one_session.last_created_at ), Questions AS ( SELECT @@ -4532,16 +4698,16 @@ type QuestionsStatisticsParams struct { } type QuestionsStatisticsRow struct { - CountStartFalse int64 `db:"count_start_false" json:"count_start_false"` - CountStartTrue int64 `db:"count_start_true" json:"count_start_true"` - CountFResultWithTQuestion int64 `db:"count_f_result_with_t_question" json:"count_f_result_with_t_question"` - CountTResult int64 `db:"count_t_result" json:"count_t_result"` - ResultsTitle string `db:"results_title" json:"results_title"` - ResultsPercentage float64 `db:"results_percentage" json:"results_percentage"` - QuestionsTitle string `db:"questions_title" json:"questions_title"` - QuestionsPage int16 `db:"questions_page" json:"questions_page"` - AnswerContent string `db:"answer_content" json:"answer_content"` - QuestionsPercentage float64 `db:"questions_percentage" json:"questions_percentage"` + CountStartFalse int64 `db:"count_start_false" json:"count_start_false"` + CountStartTrue int64 `db:"count_start_true" json:"count_start_true"` + CountFResultWithTQuestion int64 `db:"count_f_result_with_t_question" json:"count_f_result_with_t_question"` + CountTResult int64 `db:"count_t_result" json:"count_t_result"` + ResultsTitle string `db:"results_title" json:"results_title"` + ResultsPercentage float64 `db:"results_percentage" json:"results_percentage"` + QuestionsTitle string `db:"questions_title" json:"questions_title"` + QuestionsPage interface{} `db:"questions_page" json:"questions_page"` + AnswerContent string `db:"answer_content" json:"answer_content"` + QuestionsPercentage float64 `db:"questions_percentage" json:"questions_percentage"` } func (q *Queries) QuestionsStatistics(ctx context.Context, arg QuestionsStatisticsParams) ([]QuestionsStatisticsRow, error) { diff --git a/model/gigachat.go b/model/gigachat.go new file mode 100644 index 0000000..4b93f2a --- /dev/null +++ b/model/gigachat.go @@ -0,0 +1,49 @@ +package model + +import ( + "errors" +) + +type GigaChatMessage struct { + Role string `json:"role"` + Content string `json:"content"` +} + +type GigaChatRequest struct { + Model string `json:"model"` + Stream bool `json:"stream"` + UpdateInterval int `json:"update_interval"` + Messages []GigaChatMessage `json:"messages"` +} + +type GigaChatResponse struct { + Choices []struct { + Message struct { + Role string `json:"role"` + Content string `json:"content"` + } `json:"message"` + } `json:"choices"` +} + +const CreatePrompt = `Ты маркетолог и копирайтер. Твоя задача — переформулировать маркетинговый вопрос так, чтобы он лучше подходил определённой целевой аудитории по полу и возрасту. +Ответ должен строго состоять из двух строк: + +{ + "title": "<переформулированный заголовок>", + "description": "<переформулированное описание>" +} + +Я напишу возраст, пол, заголовок и описание вопроса, а ты вернёшь только отформатированный результат.` + +var ReworkQuestionPrompt string = "%s %s пол.\n%s\n%s" + +var EmptyResponseErrorGigaChat = errors.New("empty response from GigaChat try again") + +type GigaChatAudience struct { + ID int64 `json:"id"` + QuizID int64 `json:"quiz_id"` + Sex bool `json:"sex"` // false - female, true - male + Age string `json:"age"` + Deleted bool `json:"deleted"` + CreatedAt int64 `json:"created_at"` +} diff --git a/model/model.go b/model/model.go index dee76a5..3fbea45 100644 --- a/model/model.go +++ b/model/model.go @@ -13,6 +13,7 @@ const ( StatusStart = "start" StatusTimeout = "timeout" StatusOffLimit = "offlimit" + StatusAI = "ai" TypeVariant = "variant" TypeImages = "images" @@ -104,6 +105,8 @@ type Question struct { CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` + + Session string `json:"session"` } // Answer record of question answer diff --git a/repository/amo/amo.go b/repository/amo/amo.go index f1d2d97..a095ebb 100644 --- a/repository/amo/amo.go +++ b/repository/amo/amo.go @@ -53,11 +53,15 @@ func (r *AmoRepository) GettingUserWithPagination(ctx context.Context, req *mode Deleted: row.Deleted, CreatedAt: row.Createdat, } - count = row.TotalCount users = append(users, user) } + count, err = r.queries.GetUsersCount(ctx, accountID) + if err != nil { + return nil, err + } + resp := model.UserListResp{ Count: count, Items: users, @@ -299,7 +303,6 @@ func (r *AmoRepository) GetPipelinesWithPagination(ctx context.Context, req *mod var pipelines []model.Pipeline for _, row := range rows { - count = row.TotalCount pipeline := model.Pipeline{ ID: row.ID, Amoid: row.Amoid, @@ -311,6 +314,11 @@ func (r *AmoRepository) GetPipelinesWithPagination(ctx context.Context, req *mod pipelines = append(pipelines, pipeline) } + count, err = r.queries.GetPipelinesCount(ctx, accountID) + if err != nil { + return nil, err + } + resp := model.UserListPipelinesResp{ Count: count, Items: pipelines, @@ -400,7 +408,6 @@ func (r *AmoRepository) GetStepsWithPagination(ctx context.Context, req *model.P var steps []model.Step for _, row := range rows { - count = row.TotalCount step := model.Step{ ID: row.ID, Amoid: row.Amoid, @@ -413,6 +420,14 @@ func (r *AmoRepository) GetStepsWithPagination(ctx context.Context, req *model.P steps = append(steps, step) } + count, err = r.queries.GetStepsCount(ctx, sqlcgen.GetStepsCountParams{ + Accountid: accountID, + Pipelineid: pipelineID, + }) + if err != nil { + return nil, err + } + resp := model.UserListStepsResp{ Count: count, Items: steps, @@ -505,8 +520,6 @@ func (r *AmoRepository) GetTagsWithPagination(ctx context.Context, req *model.Pa var count int64 var tags []model.Tag for _, row := range rows { - count = row.TotalCount - var entity model.EntityType v := string(row.Entity.([]byte)) entity = model.EntityType(v) @@ -523,6 +536,11 @@ func (r *AmoRepository) GetTagsWithPagination(ctx context.Context, req *model.Pa tags = append(tags, tag) } + count, err = r.queries.GetTagsCount(ctx, accountID) + if err != nil { + return nil, err + } + resp := model.UserListTagsResp{ Count: count, Items: tags, @@ -625,8 +643,6 @@ func (r *AmoRepository) GetFieldsWithPagination(ctx context.Context, req *model. var fields []model.Field for _, row := range rows { - count = row.TotalCount - var entity model.EntityType v := string(row.Entity.([]byte)) entity = model.EntityType(v) @@ -649,6 +665,11 @@ func (r *AmoRepository) GetFieldsWithPagination(ctx context.Context, req *model. fields = append(fields, field) } + count, err = r.queries.GetFieldsCount(ctx, accountID) + if err != nil { + return nil, err + } + resp := model.UserListFieldsResp{ Count: count, Items: fields, @@ -828,8 +849,11 @@ func (r *AmoRepository) SetQuizSettings(ctx context.Context, request *model.Rule return nil } -func (r *AmoRepository) GettingQuizRules(ctx context.Context, quizID int) (*model.Rule, error) { - row, err := r.queries.GetQuizRule(ctx, int32(quizID)) +func (r *AmoRepository) GettingQuizRules(ctx context.Context, accountID string, quizID int) (*model.Rule, error) { + row, err := r.queries.GetQuizRule(ctx, sqlcgen.GetQuizRuleParams{ + Quizid: int32(quizID), + Accountid: accountID, + }) if err != nil { return nil, err } diff --git a/repository/question/question.go b/repository/question/question.go index 25cec6e..6c07758 100644 --- a/repository/question/question.go +++ b/repository/question/question.go @@ -43,6 +43,7 @@ func (r *QuestionRepository) CreateQuestion(ctx context.Context, record *model.Q Content: sql.NullString{String: record.Content, Valid: true}, ParentIds: record.ParentIds, UpdatedAt: sql.NullTime{Time: time.Now(), Valid: true}, + Session: record.Session, } data, err := r.queries.InsertQuestion(ctx, params) @@ -159,6 +160,7 @@ func (r *QuestionRepository) GetQuestionList( &pIds, &piece.CreatedAt, &piece.UpdatedAt, + &piece.Session, ); err != nil { qerr = err return @@ -489,6 +491,47 @@ func (r *QuestionRepository) GetQuestionListByIDs(ctx context.Context, ids []int return questions, nil } +func (r *QuestionRepository) GetQuestionsAI(ctx context.Context, quizID int64, session string, limit, offset int32) ([]model.Question, uint64, error) { + rows, err := r.queries.GetQuestionsAI(ctx, sqlcgen.GetQuestionsAIParams{ + QuizID: quizID, + Session: session, + Limit: limit, + Offset: offset, + }) + if err != nil { + return nil, 0, err + } + + var questions []model.Question + var count int64 + + for _, row := range rows { + questions = append(questions, 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, + Session: row.Session, + }) + } + + count, err = r.queries.GetQuestionsAICount(ctx, sqlcgen.GetQuestionsAICountParams{ + QuizID: quizID, + Session: session, + }) + + return questions, uint64(count), nil +} + func (r *QuestionRepository) CheckQuestionOwner(ctx context.Context, accountID string, questionID uint64) (bool, error) { id, err := r.queries.CheckQuestionOwner(ctx, sqlcgen.CheckQuestionOwnerParams{ ID: int64(questionID), diff --git a/repository/quiz/quiz.go b/repository/quiz/quiz.go index 98c2ad9..93273a6 100644 --- a/repository/quiz/quiz.go +++ b/repository/quiz/quiz.go @@ -272,7 +272,7 @@ SELECT * FROM quiz WHERE deleted = false AND archived = false AND - status = 'start' AND + (status = 'start' OR status = 'ai') AND qid = $1; `, qid) if err != nil { @@ -662,6 +662,54 @@ func (r *QuizRepository) TemplateCopy(ctx context.Context, accountID, qID string return quizID, nil } +type DepsCreateQuizAudience struct { + QuizID int64 `json:"quiz_id"` + Sex bool `json:"sex"` // false - female, true - male + Age string `json:"age"` +} + +func (r *QuizRepository) CreateQuizAudience(ctx context.Context, audience DepsCreateQuizAudience) (int64, error) { + result, err := r.queries.CreateQuizAudience(ctx, sqlcgen.CreateQuizAudienceParams{ + Quizid: audience.QuizID, + Sex: audience.Sex, + Age: audience.Age, + }) + if err != nil { + return 0, err + } + return result, nil +} + +func (r *QuizRepository) GetQuizAudience(ctx context.Context, quizID int64) ([]model.GigaChatAudience, error) { + rows, err := r.queries.GetQuizAudience(ctx, quizID) + if err != nil { + return nil, err + } + + var audiences []model.GigaChatAudience + for _, row := range rows { + audiences = append(audiences, model.GigaChatAudience{ + ID: row.ID, + QuizID: row.ID, + Sex: row.Sex, + Age: row.Age, + Deleted: row.Deleted, + CreatedAt: row.Createdat.Time.Unix(), + }) + } + + return audiences, nil +} + +func (r *QuizRepository) DeleteQuizAudience(ctx context.Context, quizID int64) error { + err := r.queries.DeleteQuizAudience(ctx, quizID) + if err != nil { + return err + } + return nil +} + + func (r *QuizRepository) CheckQuizOwner(ctx context.Context, accountID string, quizID uint64) (bool, error) { id, err := r.queries.CheckQuizOwner(ctx, sqlcgen.CheckQuizOwnerParams{ Accountid: accountID, diff --git a/repository/result/result.go b/repository/result/result.go index 291430f..b1c441e 100644 --- a/repository/result/result.go +++ b/repository/result/result.go @@ -143,6 +143,11 @@ FROM ordered_content a WHERE EXISTS ( queryParams = append(queryParams, reqExport.New) } + mainQuery += ` AND EXISTS ( + SELECT 1 FROM answer as a2 + WHERE a2.session = a.session AND a2.result = TRUE AND a2.quiz_id = a.quiz_id + )` + mainQuery += ` ORDER BY a.session, a.question_id ASC, a.created_at DESC, a.result DESC` rows, err := r.pool.QueryContext(ctx, mainQuery, queryParams...) diff --git a/tests/integration/questionRepo_test.go b/tests/integration/questionRepo_test.go new file mode 100644 index 0000000..20e660a --- /dev/null +++ b/tests/integration/questionRepo_test.go @@ -0,0 +1,30 @@ +package integration + +import ( + "context" + "fmt" + "gitea.pena/SQuiz/common/dal" + "testing" +) + +func Test_GetQuestionList(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + d, err := dal.New(ctx, "host=localhost port=35432 user=squiz password=Redalert2 dbname=squiz sslmode=disable", nil) + if err != nil { + t.Fatal(err) + } + + defer d.Close() + + limit := int32(10) + offset := int32(1000) + + list, count, err := d.QuestionRepo.GetQuestionsAI(ctx, 1308, "", limit, offset) + if err != nil { + t.Fatal(err) + } + fmt.Println(list) + fmt.Println(count) + +}