megre main into leadTarget
This commit is contained in:
commit
c23fda5f3f
46
dal/dal.go
46
dal/dal.go
@ -5,6 +5,8 @@ import (
|
||||
"database/sql"
|
||||
_ "embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
_ "github.com/ClickHouse/clickhouse-go"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/minio/minio-go/v7"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/dal/sqlcgen"
|
||||
@ -31,6 +33,7 @@ type DAL struct {
|
||||
ResultRepo *result.ResultRepository
|
||||
WorkerRepo *workers.WorkerRepository
|
||||
StatisticsRepo *statistics.StatisticsRepository
|
||||
WorkerAnsRepo *answer.WorkerAnswerRepository
|
||||
}
|
||||
|
||||
func New(ctx context.Context, cred string, minioClient *minio.Client) (*DAL, error) {
|
||||
@ -62,12 +65,17 @@ func New(ctx context.Context, cred string, minioClient *minio.Client) (*DAL, err
|
||||
}
|
||||
}
|
||||
|
||||
answerRepo := answer.NewAnswerRepository(answer.Deps{
|
||||
workerAnsRepo := answer.NewWorkerAnswerRepo(answer.Deps{
|
||||
Queries: queries,
|
||||
Pool: pool,
|
||||
AnswerMinio: storerAnswer,
|
||||
})
|
||||
|
||||
answerRepo := answer.NewAnswerRepository(answer.Deps{
|
||||
Queries: queries,
|
||||
Pool: pool,
|
||||
})
|
||||
|
||||
questionRepo := question.NewQuestionRepository(question.Deps{
|
||||
Queries: queries,
|
||||
Pool: pool,
|
||||
@ -102,6 +110,7 @@ func New(ctx context.Context, cred string, minioClient *minio.Client) (*DAL, err
|
||||
ResultRepo: resultRepo,
|
||||
WorkerRepo: workerRepo,
|
||||
StatisticsRepo: statisticsRepo,
|
||||
WorkerAnsRepo: workerAnsRepo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -177,3 +186,38 @@ func (d *AmoDal) Close(ctx context.Context) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ClickHouseDAL struct {
|
||||
conn *sql.DB
|
||||
StatisticClickRepo *statistics.StatisticClick
|
||||
}
|
||||
|
||||
func NewClickHouseDAL(ctx context.Context, cred string) (*ClickHouseDAL, error) {
|
||||
conn, err := sql.Open("clickhouse", cred)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error open database connection: %w", err)
|
||||
}
|
||||
|
||||
timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := conn.PingContext(timeoutCtx); err != nil {
|
||||
return nil, fmt.Errorf("error ping database: %w", err)
|
||||
}
|
||||
|
||||
statsClickRepo, err := statistics.NewClickStatistic(ctx, statistics.DepsClick{
|
||||
Conn: conn,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ClickHouseDAL{
|
||||
conn: conn,
|
||||
StatisticClickRepo: statsClickRepo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *ClickHouseDAL) Close(ctx context.Context) error {
|
||||
return d.conn.Close()
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ INSERT INTO quiz (accountid,
|
||||
qid
|
||||
)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19)
|
||||
RETURNING id, created_at, updated_at, qid;
|
||||
RETURNING id, created_at, updated_at, qid;
|
||||
|
||||
-- name: InsertQuestion :one
|
||||
INSERT INTO question (
|
||||
@ -35,7 +35,7 @@ INSERT INTO question (
|
||||
updated_at
|
||||
)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)
|
||||
RETURNING id, created_at, updated_at;
|
||||
RETURNING id, created_at, updated_at;
|
||||
|
||||
-- name: DeleteQuestion :one
|
||||
UPDATE question SET deleted=true WHERE id=$1 RETURNING question.*;
|
||||
@ -51,7 +51,7 @@ INSERT INTO question(
|
||||
SELECT $1, title, description, questiontype, required,
|
||||
page, content, version, parent_ids
|
||||
FROM question WHERE question.id=$2
|
||||
RETURNING question.id, quiz_id, created_at, updated_at;
|
||||
RETURNING question.id, quiz_id, created_at, updated_at;
|
||||
|
||||
-- name: DuplicateQuestion :one
|
||||
INSERT INTO question(
|
||||
@ -61,7 +61,7 @@ INSERT INTO question(
|
||||
SELECT quiz_id, title, description, questiontype, required,
|
||||
page, content, version, parent_ids
|
||||
FROM question WHERE question.id=$1
|
||||
RETURNING question.id, quiz_id, created_at, updated_at;
|
||||
RETURNING question.id, quiz_id, created_at, updated_at;
|
||||
|
||||
-- name: MoveToHistory :one
|
||||
INSERT INTO question(
|
||||
@ -71,7 +71,7 @@ INSERT INTO question(
|
||||
SELECT quiz_id, title, description, questiontype, required,
|
||||
page, content, version, parent_ids, true as deleted
|
||||
FROM question WHERE question.id=$1
|
||||
RETURNING question.id, quiz_id, parent_ids;
|
||||
RETURNING question.id, quiz_id, parent_ids;
|
||||
|
||||
-- name: MoveToHistoryQuiz :one
|
||||
INSERT INTO quiz(deleted,
|
||||
@ -81,7 +81,7 @@ INSERT INTO quiz(deleted,
|
||||
SELECT true as deleted, accountid, archived,fingerprinting,repeatable,note_prevented,mail_notifications,unique_answers,name,description,config,
|
||||
status,limit_answers,due_to,time_of_passing,pausable,version,version_comment,parent_ids,questions_count,answers_count,average_time_passing, super, group_id
|
||||
FROM quiz WHERE quiz.id=$1 AND quiz.accountid=$2
|
||||
RETURNING quiz.id, qid, parent_ids;
|
||||
RETURNING quiz.id, qid, parent_ids;
|
||||
|
||||
-- name: CopyQuiz :one
|
||||
INSERT INTO quiz(
|
||||
@ -91,7 +91,7 @@ INSERT INTO quiz(
|
||||
SELECT accountid, archived,fingerprinting,repeatable,note_prevented,mail_notifications,unique_answers,name,description,config,
|
||||
status,limit_answers,due_to,time_of_passing,pausable,version,version_comment,parent_ids,questions_count, super, group_id
|
||||
FROM quiz WHERE quiz.id=$1 AND quiz.accountId=$2
|
||||
RETURNING id, qid,created_at, updated_at;
|
||||
RETURNING id, qid,created_at, updated_at;
|
||||
|
||||
-- name: CopyQuizQuestions :exec
|
||||
INSERT INTO question(
|
||||
@ -134,6 +134,7 @@ SELECT
|
||||
p.amount,
|
||||
p.created_at,
|
||||
a.id,
|
||||
a.email,
|
||||
qz.config
|
||||
FROM
|
||||
privileges AS p
|
||||
@ -143,7 +144,7 @@ WHERE
|
||||
qz.id = $1;
|
||||
|
||||
-- name: CreateAccount :one
|
||||
INSERT INTO account (id, user_id, created_at, deleted) VALUES ($1, $2, $3, $4) RETURNING *;
|
||||
INSERT INTO account (id, user_id, email, created_at, deleted) VALUES ($1, $2, $3, $4, $5) RETURNING *;;
|
||||
|
||||
-- name: DeletePrivilegeByAccID :exec
|
||||
DELETE FROM privileges WHERE account_id = $1;
|
||||
@ -232,11 +233,11 @@ SET
|
||||
answers_count = COALESCE(aa.unique_true_answers_count, 0),
|
||||
average_time_passing = COALESCE(sta.average_session_time, 0),
|
||||
sessions_count = COALESCE(sta.sess,0)
|
||||
FROM
|
||||
FROM
|
||||
(SELECT * FROM quiz WHERE deleted = FALSE AND archived = FALSE) q_sub
|
||||
LEFT JOIN answer_aggregates aa ON q_sub.id = aa.quiz_id
|
||||
LEFT JOIN question_aggregates qa ON q_sub.id = qa.quiz_id
|
||||
LEFT JOIN session_times_aggregates sta ON q_sub.id = sta.quiz_id
|
||||
LEFT JOIN answer_aggregates aa ON q_sub.id = aa.quiz_id
|
||||
LEFT JOIN question_aggregates qa ON q_sub.id = qa.quiz_id
|
||||
LEFT JOIN session_times_aggregates sta ON q_sub.id = sta.quiz_id
|
||||
WHERE
|
||||
q.id = q_sub.id;
|
||||
|
||||
@ -247,6 +248,7 @@ UPDATE privileges SET amount = $1 WHERE id = $2;
|
||||
SELECT
|
||||
a.id,
|
||||
a.user_id,
|
||||
a.email,
|
||||
a.created_at,
|
||||
COALESCE(p.ID,0),
|
||||
coalesce(p.privilegeid,''),
|
||||
@ -407,13 +409,13 @@ WITH TimeBucket AS (
|
||||
SELECT
|
||||
date_trunc('hour', timestamp_bucket)::TIMESTAMP AS time_interval_start,
|
||||
COALESCE(LEAD(
|
||||
date_trunc('hour', timestamp_bucket)::TIMESTAMP
|
||||
) OVER (ORDER BY timestamp_bucket), NOW()) AS time_interval_end
|
||||
date_trunc('hour', timestamp_bucket)::TIMESTAMP
|
||||
) OVER (ORDER BY timestamp_bucket), NOW()) AS time_interval_end
|
||||
FROM
|
||||
generate_series(TO_TIMESTAMP($1), TO_TIMESTAMP($2), CASE
|
||||
WHEN EXTRACT(epoch FROM TO_TIMESTAMP($2)) - EXTRACT(epoch FROM TO_TIMESTAMP($1)) > 172800 THEN '1 day'::interval
|
||||
ELSE '1 hour'::interval
|
||||
END) AS timestamp_bucket
|
||||
generate_series(TO_TIMESTAMP($1), TO_TIMESTAMP($2), CASE
|
||||
WHEN EXTRACT(epoch FROM TO_TIMESTAMP($2)) - EXTRACT(epoch FROM TO_TIMESTAMP($1)) > 172800 THEN '1 day'::interval
|
||||
ELSE '1 hour'::interval
|
||||
END) AS timestamp_bucket
|
||||
),
|
||||
OpenStats AS (
|
||||
SELECT
|
||||
@ -494,7 +496,7 @@ SELECT
|
||||
CASE
|
||||
WHEN COALESCE(os.open_count, 0) > 0 THEN COALESCE(rs.true_result_count, 0)::float / COALESCE(os.open_count, 0)::float
|
||||
ELSE 0
|
||||
END::float AS conversion,
|
||||
END::float AS conversion,
|
||||
COALESCE(at.avg_time, 0) AS avg_time
|
||||
FROM
|
||||
TimeBucket tb
|
||||
@ -511,10 +513,10 @@ FROM
|
||||
-- name: QuestionsStatistics :many
|
||||
WITH 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
|
||||
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
|
||||
LEFT JOIN (
|
||||
@ -529,23 +531,23 @@ WITH Funnel AS (
|
||||
AND a.created_at <= TO_TIMESTAMP($3)
|
||||
),
|
||||
Results AS (
|
||||
SELECT
|
||||
COALESCE(q.title, '') AS question_title,
|
||||
COUNT(*) AS total_answers,
|
||||
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
|
||||
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
|
||||
HAVING
|
||||
COUNT(*) >= 1
|
||||
),
|
||||
SELECT
|
||||
COALESCE(q.title, '') AS question_title,
|
||||
COUNT(*) AS total_answers,
|
||||
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
|
||||
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
|
||||
HAVING
|
||||
COUNT(*) >= 1
|
||||
),
|
||||
LastContent AS (
|
||||
SELECT
|
||||
a.question_id,
|
||||
@ -561,35 +563,35 @@ WITH Funnel AS (
|
||||
answer
|
||||
WHERE
|
||||
quiz_id = $1
|
||||
AND start != true
|
||||
AND start != true
|
||||
AND created_at >= TO_TIMESTAMP($2)
|
||||
AND created_at <= TO_TIMESTAMP($3)
|
||||
GROUP BY
|
||||
question_id, session
|
||||
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
|
||||
),
|
||||
Questions AS (
|
||||
SELECT
|
||||
q.title AS question_title,
|
||||
q.page AS question_page,
|
||||
lc.last_answer_content AS answer_content,
|
||||
CAST(
|
||||
COUNT(CASE WHEN a.result = FALSE THEN 1 END) * 100.0 / NULLIF(SUM(COUNT(CASE WHEN a.result = FALSE THEN 1 END)) OVER (PARTITION BY q.id), 0) AS FLOAT8
|
||||
) AS percentage
|
||||
FROM
|
||||
question q
|
||||
JOIN LastContent lc ON q.id = lc.question_id
|
||||
JOIN answer a ON q.id = a.question_id
|
||||
WHERE
|
||||
a.quiz_id = $1
|
||||
AND a.start != true
|
||||
AND a.created_at >= TO_TIMESTAMP($2)
|
||||
AND a.created_at <= TO_TIMESTAMP($3)
|
||||
GROUP BY
|
||||
q.id, q.title, lc.last_answer_content
|
||||
HAVING
|
||||
COUNT(*) >= 1
|
||||
)
|
||||
SELECT
|
||||
q.title AS question_title,
|
||||
q.page AS question_page,
|
||||
lc.last_answer_content AS answer_content,
|
||||
CAST(
|
||||
COUNT(CASE WHEN a.result = FALSE THEN 1 END) * 100.0 / NULLIF(SUM(COUNT(CASE WHEN a.result = FALSE THEN 1 END)) OVER (PARTITION BY q.id), 0) AS FLOAT8
|
||||
) AS percentage
|
||||
FROM
|
||||
question q
|
||||
JOIN LastContent lc ON q.id = lc.question_id
|
||||
JOIN answer a ON q.id = a.question_id
|
||||
WHERE
|
||||
a.quiz_id = $1
|
||||
AND a.start != true
|
||||
AND a.created_at >= TO_TIMESTAMP($2)
|
||||
AND a.created_at <= TO_TIMESTAMP($3)
|
||||
GROUP BY
|
||||
q.id, q.title, lc.last_answer_content
|
||||
HAVING
|
||||
COUNT(*) >= 1
|
||||
)
|
||||
SELECT
|
||||
Funnel.count_start_false,
|
||||
Funnel.count_start_true,
|
||||
@ -603,34 +605,34 @@ SELECT
|
||||
COALESCE(Questions.percentage, 0) AS questions_percentage
|
||||
FROM
|
||||
Funnel
|
||||
LEFT JOIN Results ON true
|
||||
LEFT JOIN Questions ON Questions.percentage >= 1;
|
||||
LEFT JOIN Results ON true
|
||||
LEFT JOIN Questions ON Questions.percentage >= 1;
|
||||
|
||||
-- name: QuizCopyQid :one
|
||||
INSERT INTO quiz (
|
||||
accountid, archived, fingerprinting, repeatable, note_prevented, mail_notifications, unique_answers, name, description, config,
|
||||
status, limit_answers, due_to, time_of_passing, pausable, version, version_comment, parent_ids, questions_count, answers_count, average_time_passing, super, group_id
|
||||
)
|
||||
SELECT
|
||||
$2, archived, fingerprinting, repeatable, note_prevented, mail_notifications, unique_answers, name, description, config,
|
||||
status, limit_answers, due_to, time_of_passing, pausable, version, version_comment, parent_ids, questions_count, answers_count, average_time_passing, super, group_id
|
||||
FROM
|
||||
quiz as q
|
||||
WHERE
|
||||
q.qid = $1
|
||||
RETURNING (select id from quiz where qid = $1),id, qid;
|
||||
|
||||
INSERT INTO quiz (
|
||||
accountid, archived, fingerprinting, repeatable, note_prevented, mail_notifications, unique_answers, name, description, config,
|
||||
status, limit_answers, due_to, time_of_passing, pausable, version, version_comment, parent_ids, questions_count, answers_count, average_time_passing, super, group_id
|
||||
)
|
||||
SELECT
|
||||
$2, archived, fingerprinting, repeatable, note_prevented, mail_notifications, unique_answers, name, description, config,
|
||||
status, limit_answers, due_to, time_of_passing, pausable, version, version_comment, parent_ids, questions_count, answers_count, average_time_passing, super, group_id
|
||||
FROM
|
||||
quiz as q
|
||||
WHERE
|
||||
q.qid = $1
|
||||
RETURNING (select id from quiz where qid = $1),id, qid;
|
||||
|
||||
-- name: CopyQuestionQuizID :exec
|
||||
INSERT INTO question (
|
||||
quiz_id, title, description, questiontype, required,
|
||||
page, content, version, parent_ids, created_at, updated_at
|
||||
)
|
||||
SELECT
|
||||
SELECT
|
||||
$2, title, description, questiontype, required,
|
||||
page, content, version, parent_ids, created_at, updated_at
|
||||
FROM
|
||||
FROM
|
||||
question
|
||||
WHERE
|
||||
WHERE
|
||||
question.quiz_id = $1 AND deleted = false;
|
||||
|
||||
-- name: GetQidOwner :one
|
||||
@ -656,7 +658,7 @@ SELECT
|
||||
(SELECT registration_count FROM Registrations) AS registrations,
|
||||
(SELECT quiz_count FROM Quizes) AS quizes,
|
||||
(SELECT result_count FROM Results) AS results;
|
||||
|
||||
|
||||
-- name: GetListStartQuiz :many
|
||||
SELECT id FROM quiz WHERE accountid = $1 AND status = 'start';
|
||||
|
||||
@ -684,8 +686,8 @@ RETURNING quiz_id;
|
||||
-- amo methods:
|
||||
|
||||
-- name: CreateAmoAccount :exec
|
||||
INSERT INTO users (AccountID, AmoID, Name, Email, Role, "Group", Deleted, CreatedAt, Subdomain, AmoUserID, Country,DriveURL)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);
|
||||
INSERT INTO accountsAmo (AccountID, AmoID,Name, Subdomain, Country,DriveURL)
|
||||
VALUES ($1, $2, $3, $4, $5, $6);
|
||||
|
||||
-- name: CreateWebHook :exec
|
||||
INSERT INTO tokens (AccountID, RefreshToken, AccessToken, AuthCode, Expiration, CreatedAt)
|
||||
@ -698,61 +700,80 @@ WHERE accountID = $5;
|
||||
-- name: GetAllTokens :many
|
||||
SELECT * FROM tokens;
|
||||
|
||||
-- name: CheckExpired :many
|
||||
SELECT * FROM tokens WHERE Expiration <= TO_TIMESTAMP(EXTRACT(EPOCH FROM NOW()) + (10 * 60));
|
||||
-- name: CheckExpiredToken :one
|
||||
SELECT * FROM tokens WHERE AccountID = $1 AND Expiration <= NOW();
|
||||
|
||||
-- name: UpdateAmoAccount :exec
|
||||
UPDATE accountsAmo SET Name = $2, Subdomain = $3, Country = $4, DriveURL = $5 WHERE AccountID = $1 AND Deleted = false;
|
||||
|
||||
-- name: WebhookDelete :exec
|
||||
WITH userd AS (
|
||||
UPDATE users SET Deleted = true WHERE AmoUserID = $1 RETURNING AccountID
|
||||
)
|
||||
DELETE FROM tokens WHERE AccountID IN (SELECT AccountID FROM userd);
|
||||
WITH companyDel AS (
|
||||
UPDATE accountsAmo SET Deleted = true WHERE accountsAmo.AmoID = $1 RETURNING AccountID
|
||||
),
|
||||
userDel AS (
|
||||
UPDATE usersAmo SET Deleted = true WHERE AmoID = $1
|
||||
)
|
||||
DELETE FROM tokens WHERE AccountID IN (SELECT AccountID FROM companyDel);
|
||||
|
||||
-- name: SoftDeleteAccount :exec
|
||||
WITH userd AS (
|
||||
SELECT AmoUserID FROM users WHERE users.AccountID = $1
|
||||
WITH amoCompany AS (
|
||||
SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1
|
||||
),usersDel AS (
|
||||
UPDATE usersAmo SET Deleted = true WHERE AmoID = (SELECT AmoID FROM amoCompany)
|
||||
),
|
||||
tokend AS (
|
||||
UPDATE users SET Deleted = true WHERE AmoUserID IN (SELECT AmoUserID FROM userd)
|
||||
companyDel AS ( UPDATE accountsAmo SET Deleted = true WHERE AmoID = (SELECT AmoID FROM amoCompany)
|
||||
)
|
||||
DELETE FROM tokens WHERE tokens.AccountID = $1;
|
||||
|
||||
-- name: GetCurrentAccount :one
|
||||
SELECT * FROM users WHERE AccountID = $1 AND Deleted = false;
|
||||
-- name: GetCurrentCompany :one
|
||||
SELECT * FROM accountsAmo WHERE AccountID = $1 AND Deleted = false;
|
||||
|
||||
-- name: CheckMainUser :exec
|
||||
UPDATE users SET Name = $1, "Group" = $2, Email = $3, Role = $4 WHERE AmoID = $5;
|
||||
-- name: GetAllCompanyUsers :many
|
||||
SELECT * FROM usersamo WHERE amoid = $1 AND deleted = false;
|
||||
|
||||
-- name: GetUsersWithPagination :many
|
||||
WITH user_data AS (
|
||||
SELECT AmoID FROM users WHERE users.AccountID = $1 AND Deleted = false
|
||||
SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false
|
||||
)
|
||||
SELECT u.*, COUNT(*) OVER() as total_count
|
||||
FROM users u
|
||||
JOIN user_data a ON u.AmoUserID = a.AmoID
|
||||
SELECT u.*, COUNT(*) OVER() as total_count
|
||||
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: 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
|
||||
FROM tags t JOIN (SELECT AmoID FROM users WHERE users.AccountID = $1 AND Deleted = false) u ON t.AccountID = u.AmoID
|
||||
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: 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
|
||||
FROM steps s JOIN (SELECT AmoID FROM users WHERE users.AccountID = $1 AND Deleted = false) u ON s.AccountID = u.AmoID
|
||||
FROM steps s JOIN user_data u ON s.AccountID = u.AmoID
|
||||
WHERE s.Deleted = false AND PipelineID = $4
|
||||
ORDER BY s.ID OFFSET ($2 - 1) * $3 LIMIT $3;
|
||||
|
||||
-- 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
|
||||
FROM pipelines p JOIN (SELECT AmoID FROM users WHERE users.AccountID = $1 AND Deleted = false) u ON p.AccountID = u.AmoID
|
||||
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: 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
|
||||
FROM fields f JOIN (SELECT AmoID FROM users WHERE users.AccountID = $1 AND Deleted = false) u ON f.AccountID = u.AmoID
|
||||
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;
|
||||
|
||||
@ -791,12 +812,10 @@ FROM json_array_elements($1::json) AS update_data
|
||||
WHERE f.amoID = (update_data ->> 'AmoID')::INT
|
||||
AND f.accountID = (update_data ->> 'AccountID')::INT
|
||||
AND f.Entity = (update_data ->> 'Entity')::entitytype;
|
||||
|
||||
|
||||
-- name: CheckTags :many
|
||||
WITH user_data AS (
|
||||
SELECT AmoID
|
||||
FROM users
|
||||
WHERE users.AccountID = $1
|
||||
SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false
|
||||
), new_tags AS (
|
||||
SELECT (tag->>'AmoID')::INT AS amoID,
|
||||
(tag->>'Entity')::entitytype AS Entity,
|
||||
@ -818,7 +837,7 @@ WITH user_data AS (
|
||||
)
|
||||
SELECT nt.*,ud.AmoID
|
||||
FROM new_tags nt
|
||||
JOIN user_data ud ON true
|
||||
JOIN user_data ud ON true
|
||||
WHERE NOT EXISTS (
|
||||
SELECT *
|
||||
FROM inserted_tags ins
|
||||
@ -836,14 +855,14 @@ WITH new_pipelines AS (
|
||||
FROM json_array_elements($1::json) AS pipeline
|
||||
), inserted_pipelines AS(
|
||||
INSERT INTO pipelines (amoID, accountID, name, isArchive, createdAt)
|
||||
SELECT np.amoID,
|
||||
np.accountID,
|
||||
np.name,
|
||||
np.isArchive,
|
||||
np.createdAt
|
||||
FROM new_pipelines np
|
||||
ON CONFLICT (amoID, accountID) DO NOTHING
|
||||
RETURNING *
|
||||
SELECT np.amoID,
|
||||
np.accountID,
|
||||
np.name,
|
||||
np.isArchive,
|
||||
np.createdAt
|
||||
FROM new_pipelines np
|
||||
ON CONFLICT (amoID, accountID) DO NOTHING
|
||||
RETURNING *
|
||||
)
|
||||
SELECT np.*
|
||||
FROM new_pipelines np
|
||||
@ -855,34 +874,32 @@ WHERE NOT EXISTS (
|
||||
|
||||
-- name: CheckFields :many
|
||||
WITH user_data AS (
|
||||
SELECT AmoID
|
||||
FROM users
|
||||
WHERE users.AccountID = $1
|
||||
SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false
|
||||
), new_fields AS (
|
||||
SELECT (field->>'AmoID')::INT AS amoID,
|
||||
COALESCE(field->>'Code', '')::varchar(255) AS code,
|
||||
COALESCE(field->>'Name', '')::varchar(512) AS name,
|
||||
CAST(field->>'Entity' AS entitytype) AS Entity,
|
||||
COALESCE(field->>'Type', '')::fieldtype AS type,
|
||||
CURRENT_TIMESTAMP AS createdAt
|
||||
COALESCE(field->>'Code', '')::varchar(255) AS code,
|
||||
COALESCE(field->>'Name', '')::varchar(512) AS name,
|
||||
CAST(field->>'Entity' AS entitytype) AS Entity,
|
||||
COALESCE(field->>'Type', '')::fieldtype AS type,
|
||||
CURRENT_TIMESTAMP AS createdAt
|
||||
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 NOTHING
|
||||
RETURNING *
|
||||
)
|
||||
SELECT nf.*,ud.AmoID
|
||||
FROM new_fields nf
|
||||
JOIN user_data ud ON true
|
||||
JOIN user_data ud ON true
|
||||
WHERE NOT EXISTS (
|
||||
SELECT *
|
||||
FROM inserted_fields ins
|
||||
@ -901,15 +918,15 @@ WITH new_steps AS (
|
||||
FROM json_array_elements($1::json) AS step
|
||||
), inserted_steps AS (
|
||||
INSERT INTO steps (amoID, pipelineID, accountID, name, color, createdAt)
|
||||
SELECT ns.amoID,
|
||||
ns.pipelineID,
|
||||
ns.accountID,
|
||||
ns.name,
|
||||
ns.color,
|
||||
ns.createdAt
|
||||
FROM new_steps ns
|
||||
ON CONFLICT (amoID, accountID, PipelineID) DO NOTHING
|
||||
RETURNING *
|
||||
SELECT ns.amoID,
|
||||
ns.pipelineID,
|
||||
ns.accountID,
|
||||
ns.name,
|
||||
ns.color,
|
||||
ns.createdAt
|
||||
FROM new_steps ns
|
||||
ON CONFLICT (amoID, accountID, PipelineID) DO NOTHING
|
||||
RETURNING *
|
||||
)
|
||||
SELECT ns.*
|
||||
FROM new_steps ns
|
||||
@ -928,13 +945,13 @@ SELECT * FROM rules WHERE QuizID = $1 AND Deleted = false;
|
||||
-- name: SetQuizSettings :one
|
||||
INSERT INTO rules (AccountID, QuizID, PerformerID, PipelineID, StepID, FieldsRule,TagsToAdd)
|
||||
SELECT u.AmoID AS AccountID,$1 AS QuizID,$2 AS PerformerID,$3 AS PipelineID,
|
||||
$4 AS StepID,$5 AS FieldsRule,$6 AS TagsToAdd FROM users u WHERE u.AccountID = $7 AND u.Deleted = false
|
||||
RETURNING id;
|
||||
$4 AS StepID,$5 AS FieldsRule,$6 AS TagsToAdd FROM accountsamo u WHERE u.AccountID = $7 AND u.Deleted = false
|
||||
RETURNING id;
|
||||
|
||||
-- name: ChangeQuizSettings :one
|
||||
UPDATE rules
|
||||
SET PerformerID = $1,PipelineID = $2,StepID = $3,FieldsRule = $4, TagsToAdd=$5
|
||||
WHERE AccountID = (SELECT AmoID FROM users WHERE users.AccountID = $6 AND users.Deleted = false) AND QuizID = $7 AND Deleted = false
|
||||
WHERE AccountID = (SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $6 AND accountsAmo.Deleted = false) AND QuizID = $7 AND Deleted = false
|
||||
RETURNING id;
|
||||
|
||||
-- name: GetQuestionListByIDs :many
|
||||
@ -942,62 +959,29 @@ SELECT * FROM question WHERE id = ANY($1::int[]) AND deleted = FALSE;
|
||||
|
||||
-- name: UpdateFieldRules :exec
|
||||
UPDATE rules SET FieldsRule = $1
|
||||
WHERE AccountID = (SELECT AmoID FROM users WHERE users.AccountID = $2 AND users.Deleted = false) AND QuizID = $3 AND Deleted = false;
|
||||
WHERE AccountID = (SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $2 AND accountsAmo.Deleted = false) AND QuizID = $3 AND Deleted = false;
|
||||
|
||||
-- name: UpdateUsers :exec
|
||||
UPDATE users AS u
|
||||
SET Name = (update_data ->> 'Name')::varchar(512),
|
||||
Email = (update_data ->> 'Email')::varchar(50),
|
||||
Role = (update_data ->> 'Role')::INT,
|
||||
"Group" = (update_data ->> 'Group')::INT,
|
||||
AmoUserID= (update_data ->> 'AmoUserID')::INT
|
||||
FROM json_array_elements($1::json) AS update_data
|
||||
WHERE u.AmoID = (update_data ->> 'AmocrmID')::INT;
|
||||
-- name: UpdateAmoAccountUser :exec
|
||||
UPDATE usersAmo SET Name = $3, Email = $4, Role = $5, "Group" = $6
|
||||
WHERE AmoID = $1 AND AmoUserID = $2 AND deleted = false;
|
||||
|
||||
-- name: CheckUsers :many
|
||||
WITH new_users AS (
|
||||
SELECT (u->>'AmocrmID')::INT AS AmoID,
|
||||
(u->>'Name')::VARCHAR(512) AS Name,
|
||||
(u->>'Group')::INT AS "Group",
|
||||
(u->>'Role')::INT AS Role,
|
||||
(u->>'Email')::VARCHAR(50) AS Email,
|
||||
(u->>'AmoUserID')::INT AS AmoUserID,
|
||||
CURRENT_TIMESTAMP AS createdAt
|
||||
FROM json_array_elements($1::json) AS u
|
||||
), inserted_users AS (
|
||||
INSERT INTO users (AmoID, Name, "Group", Role, Email, AmoUserID,createdAt)
|
||||
SELECT nu.AmoID,
|
||||
nu.Name,
|
||||
nu."Group",
|
||||
nu.Role,
|
||||
nu.Email,
|
||||
nu.AmoUserID,
|
||||
nu.createdAt
|
||||
FROM new_users nu
|
||||
ON CONFLICT (amoID) DO NOTHING
|
||||
RETURNING *
|
||||
)
|
||||
SELECT nu.*
|
||||
FROM new_users nu
|
||||
WHERE NOT EXISTS (
|
||||
SELECT *
|
||||
FROM inserted_users ins
|
||||
WHERE ins.amoID = nu.amoID
|
||||
);
|
||||
-- name: AddAmoAccountUser :exec
|
||||
INSERT INTO usersAmo (AmoID, AmoUserID, Name, Email, Role, "Group")
|
||||
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,
|
||||
(SELECT a2.utm
|
||||
FROM answer a2
|
||||
WHERE a2.start = true AND a2.session = a.session
|
||||
LIMIT 1) AS utm
|
||||
,t.accesstoken,r.accountid,r.fieldsrule,r.tagstoadd,r.performerid,r.stepid,r.pipelineid,(SELECT u.name FROM users u WHERE u.amoid = r.performerid) 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.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
|
||||
INNER JOIN rules r ON q.id = r.QuizID
|
||||
INNER JOIN tokens t ON q.accountid = t.AccountID
|
||||
INNER JOIN users u ON q.accountid = u.accountid AND u.amoid = r.accountid
|
||||
INNER JOIN accountsAmo u ON q.accountid = u.accountid AND u.amoid = r.accountid
|
||||
WHERE a.result = true
|
||||
AND s.id IS NULL
|
||||
AND a.deleted = false
|
||||
@ -1009,12 +993,12 @@ WHERE a.result = true
|
||||
INSERT INTO amoCRMStatuses (AccountID, DealID, AnswerID, Status)
|
||||
SELECT u.AmoID, $1, $2, $3
|
||||
FROM tokens AS t
|
||||
JOIN users AS u ON t.AccountID = u.AccountID
|
||||
JOIN accountsAmo AS u ON t.AccountID = u.AccountID
|
||||
WHERE t.AccessToken = $4 AND u.Deleted = false;
|
||||
|
||||
-- name: UpdatingDealAmoStatus :exec
|
||||
UPDATE amoCRMStatuses SET Status = $1
|
||||
WHERE DealID = $2 AND AccountID = (SELECT u.AmoID FROM tokens AS t JOIN users AS u ON t.AccountID = u.AccountID WHERE t.AccessToken = $3 AND u.Deleted = false);
|
||||
WHERE DealID = $2 AND AccountID = (SELECT u.AmoID FROM tokens AS t JOIN accountsAmo AS u ON t.AccountID = u.AccountID WHERE t.AccessToken = $3 AND u.Deleted = false);
|
||||
|
||||
-- name: DeleteFields :exec
|
||||
UPDATE fields SET Deleted = true WHERE ID = ANY($1::bigint[]);
|
||||
@ -1029,7 +1013,7 @@ UPDATE steps SET Deleted = true WHERE ID = ANY($1::bigint[]);
|
||||
UPDATE pipelines SET Deleted = true WHERE ID = ANY($1::bigint[]);
|
||||
|
||||
-- name: DeleteUsers :exec
|
||||
UPDATE users SET Deleted = true WHERE ID = ANY($1::bigint[]);
|
||||
UPDATE usersAmo SET Deleted = true WHERE ID = ANY($1::bigint[]);
|
||||
|
||||
-- name: GetUserTagsByID :many
|
||||
SELECT ID,AmoID,AccountID,Name,Entity,Color
|
||||
@ -1047,9 +1031,7 @@ FROM pipelines
|
||||
WHERE AccountID = $1 AND Deleted = false;
|
||||
|
||||
-- name: GetUserUsersByID :many
|
||||
SELECT ID,AccountID,AmoID,Name,Email,Role,"Group",Subdomain,AmoUserID,Country
|
||||
FROM users
|
||||
WHERE AmoUserID = $1 AND Deleted = false;
|
||||
SELECT * FROM usersAmo WHERE amoid = $1 AND Deleted = false;
|
||||
|
||||
-- name: GetFieldByAmoID :one
|
||||
SELECT * FROM fields WHERE AmoID = $1 AND Deleted = false;
|
||||
@ -1062,7 +1044,19 @@ WHERE AccountID = $1 AND Deleted = false;
|
||||
-- name: DecrementManual :one
|
||||
UPDATE privileges p SET amount = amount - 1 FROM account a
|
||||
WHERE p.account_id = a.id AND a.user_id = $1 AND p.privilegeID = $2 AND p.amount > 0
|
||||
RETURNING p.id, p.privilegeID, p.account_id, p.privilege_name, p.amount, p.created_at;;
|
||||
RETURNING p.id, p.privilegeID, p.account_id, p.privilege_name, p.amount, p.created_at;
|
||||
|
||||
-- name: GetExistingContactAmo :many
|
||||
WITH getAmoID AS (
|
||||
SELECT AmoID FROM amoContact WHERE amoContact.AccountID = $1 AND amoContact.Field = ANY($2::text[])
|
||||
) SELECT * FROM amoContact
|
||||
WHERE amoContact.AccountID = $1 AND amoContact.AmoID IN (SELECT AmoID FROM getAmoID);
|
||||
|
||||
-- name: InsertContactAmo :one
|
||||
INSERT INTO amoContact (AccountID, AmoID, Field) VALUES ($1, $2, $3) RETURNING AmoID;
|
||||
|
||||
-- name: UpdateAmoContact :exec
|
||||
UPDATE amoContact SET Field = $1,AmoID=$3 WHERE ID = $2;
|
||||
|
||||
-- name: CreateLeadTarget :one
|
||||
INSERT INTO leadtarget (accountID,type,quizID,target) VALUES ($1,$2,$3,$4) RETURNING *;
|
||||
|
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
|
||||
)
|
@ -19,6 +19,25 @@ type Account struct {
|
||||
Deleted sql.NullBool `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"`
|
||||
@ -182,18 +201,14 @@ type Token struct {
|
||||
Createdat sql.NullTime `db:"createdat" json:"createdat"`
|
||||
}
|
||||
|
||||
type User 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"`
|
||||
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 sql.NullTime `db:"createdat" json:"createdat"`
|
||||
Subdomain string `db:"subdomain" json:"subdomain"`
|
||||
Amouserid int32 `db:"amouserid" json:"amouserid"`
|
||||
Country string `db:"country" json:"country"`
|
||||
Driveurl string `db:"driveurl" json:"driveurl"`
|
||||
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"`
|
||||
}
|
||||
|
@ -53,6 +53,32 @@ func (q *Queries) AccountPagination(ctx context.Context, arg AccountPaginationPa
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const addAmoAccountUser = `-- name: AddAmoAccountUser :exec
|
||||
INSERT INTO usersAmo (AmoID, AmoUserID, Name, Email, Role, "Group")
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
`
|
||||
|
||||
type AddAmoAccountUserParams struct {
|
||||
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"`
|
||||
}
|
||||
|
||||
func (q *Queries) AddAmoAccountUser(ctx context.Context, arg AddAmoAccountUserParams) error {
|
||||
_, err := q.db.ExecContext(ctx, addAmoAccountUser,
|
||||
arg.Amoid,
|
||||
arg.Amouserid,
|
||||
arg.Name,
|
||||
arg.Email,
|
||||
arg.Role,
|
||||
arg.Group,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const allServiceStatistics = `-- name: AllServiceStatistics :one
|
||||
WITH Registrations AS (
|
||||
SELECT COUNT(*) AS registration_count
|
||||
@ -110,7 +136,7 @@ func (q *Queries) ArchiveQuiz(ctx context.Context, arg ArchiveQuizParams) error
|
||||
const changeQuizSettings = `-- name: ChangeQuizSettings :one
|
||||
UPDATE rules
|
||||
SET PerformerID = $1,PipelineID = $2,StepID = $3,FieldsRule = $4, TagsToAdd=$5
|
||||
WHERE AccountID = (SELECT AmoID FROM users WHERE users.AccountID = $6 AND users.Deleted = false) AND QuizID = $7 AND Deleted = false
|
||||
WHERE AccountID = (SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $6 AND accountsAmo.Deleted = false) AND QuizID = $7 AND Deleted = false
|
||||
RETURNING id
|
||||
`
|
||||
|
||||
@ -157,45 +183,27 @@ func (q *Queries) CheckAndAddDefault(ctx context.Context, arg CheckAndAddDefault
|
||||
return err
|
||||
}
|
||||
|
||||
const checkExpired = `-- name: CheckExpired :many
|
||||
SELECT accountid, refreshtoken, accesstoken, authcode, expiration, createdat FROM tokens WHERE Expiration <= TO_TIMESTAMP(EXTRACT(EPOCH FROM NOW()) + (10 * 60))
|
||||
const checkExpiredToken = `-- name: CheckExpiredToken :one
|
||||
SELECT accountid, refreshtoken, accesstoken, authcode, expiration, createdat FROM tokens WHERE AccountID = $1 AND Expiration <= NOW()
|
||||
`
|
||||
|
||||
func (q *Queries) CheckExpired(ctx context.Context) ([]Token, error) {
|
||||
rows, err := q.db.QueryContext(ctx, checkExpired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Token
|
||||
for rows.Next() {
|
||||
var i Token
|
||||
if err := rows.Scan(
|
||||
&i.Accountid,
|
||||
&i.Refreshtoken,
|
||||
&i.Accesstoken,
|
||||
&i.Authcode,
|
||||
&i.Expiration,
|
||||
&i.Createdat,
|
||||
); 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
|
||||
func (q *Queries) CheckExpiredToken(ctx context.Context, accountid string) (Token, error) {
|
||||
row := q.db.QueryRowContext(ctx, checkExpiredToken, accountid)
|
||||
var i Token
|
||||
err := row.Scan(
|
||||
&i.Accountid,
|
||||
&i.Refreshtoken,
|
||||
&i.Accesstoken,
|
||||
&i.Authcode,
|
||||
&i.Expiration,
|
||||
&i.Createdat,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const checkFields = `-- name: CheckFields :many
|
||||
WITH user_data AS (
|
||||
SELECT AmoID
|
||||
FROM users
|
||||
WHERE users.AccountID = $1
|
||||
SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false
|
||||
), new_fields AS (
|
||||
SELECT (field->>'AmoID')::INT AS amoID,
|
||||
COALESCE(field->>'Code', '')::varchar(255) AS code,
|
||||
@ -275,29 +283,6 @@ func (q *Queries) CheckFields(ctx context.Context, arg CheckFieldsParams) ([]Che
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const checkMainUser = `-- name: CheckMainUser :exec
|
||||
UPDATE users SET Name = $1, "Group" = $2, Email = $3, Role = $4 WHERE AmoID = $5
|
||||
`
|
||||
|
||||
type CheckMainUserParams struct {
|
||||
Name string `db:"name" json:"name"`
|
||||
Group int32 `db:"Group" json:"Group"`
|
||||
Email string `db:"email" json:"email"`
|
||||
Role int32 `db:"role" json:"role"`
|
||||
Amoid int32 `db:"amoid" json:"amoid"`
|
||||
}
|
||||
|
||||
func (q *Queries) CheckMainUser(ctx context.Context, arg CheckMainUserParams) error {
|
||||
_, err := q.db.ExecContext(ctx, checkMainUser,
|
||||
arg.Name,
|
||||
arg.Group,
|
||||
arg.Email,
|
||||
arg.Role,
|
||||
arg.Amoid,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const checkPipelines = `-- name: CheckPipelines :many
|
||||
WITH new_pipelines AS (
|
||||
SELECT (pipeline->>'AmoID')::INT AS amoID,
|
||||
@ -480,9 +465,7 @@ func (q *Queries) CheckSteps(ctx context.Context, dollar_1 json.RawMessage) ([]C
|
||||
|
||||
const checkTags = `-- name: CheckTags :many
|
||||
WITH user_data AS (
|
||||
SELECT AmoID
|
||||
FROM users
|
||||
WHERE users.AccountID = $1
|
||||
SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false
|
||||
), new_tags AS (
|
||||
SELECT (tag->>'AmoID')::INT AS amoID,
|
||||
(tag->>'Entity')::entitytype AS Entity,
|
||||
@ -555,79 +538,6 @@ func (q *Queries) CheckTags(ctx context.Context, arg CheckTagsParams) ([]CheckTa
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const checkUsers = `-- name: CheckUsers :many
|
||||
WITH new_users AS (
|
||||
SELECT (u->>'AmocrmID')::INT AS AmoID,
|
||||
(u->>'Name')::VARCHAR(512) AS Name,
|
||||
(u->>'Group')::INT AS "Group",
|
||||
(u->>'Role')::INT AS Role,
|
||||
(u->>'Email')::VARCHAR(50) AS Email,
|
||||
(u->>'AmoUserID')::INT AS AmoUserID,
|
||||
CURRENT_TIMESTAMP AS createdAt
|
||||
FROM json_array_elements($1::json) AS u
|
||||
), inserted_users AS (
|
||||
INSERT INTO users (AmoID, Name, "Group", Role, Email, AmoUserID,createdAt)
|
||||
SELECT nu.AmoID,
|
||||
nu.Name,
|
||||
nu."Group",
|
||||
nu.Role,
|
||||
nu.Email,
|
||||
nu.AmoUserID,
|
||||
nu.createdAt
|
||||
FROM new_users nu
|
||||
ON CONFLICT (amoID) DO NOTHING
|
||||
RETURNING id, accountid, amoid, name, email, role, "Group", deleted, createdat, subdomain, amouserid, country, driveurl
|
||||
)
|
||||
SELECT nu.amoid, nu.name, nu."Group", nu.role, nu.email, nu.amouserid, nu.createdat
|
||||
FROM new_users nu
|
||||
WHERE NOT EXISTS (
|
||||
SELECT id, accountid, amoid, name, email, role, "Group", deleted, createdat, subdomain, amouserid, country, driveurl
|
||||
FROM inserted_users ins
|
||||
WHERE ins.amoID = nu.amoID
|
||||
)
|
||||
`
|
||||
|
||||
type CheckUsersRow struct {
|
||||
Amoid int32 `db:"amoid" json:"amoid"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Group int32 `db:"Group" json:"Group"`
|
||||
Role int32 `db:"role" json:"role"`
|
||||
Email string `db:"email" json:"email"`
|
||||
Amouserid int32 `db:"amouserid" json:"amouserid"`
|
||||
Createdat interface{} `db:"createdat" json:"createdat"`
|
||||
}
|
||||
|
||||
func (q *Queries) CheckUsers(ctx context.Context, dollar_1 json.RawMessage) ([]CheckUsersRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, checkUsers, dollar_1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []CheckUsersRow
|
||||
for rows.Next() {
|
||||
var i CheckUsersRow
|
||||
if err := rows.Scan(
|
||||
&i.Amoid,
|
||||
&i.Name,
|
||||
&i.Group,
|
||||
&i.Role,
|
||||
&i.Email,
|
||||
&i.Amouserid,
|
||||
&i.Createdat,
|
||||
); 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 copyQuestion = `-- name: CopyQuestion :one
|
||||
INSERT INTO question(
|
||||
quiz_id, title, description, questiontype, required,
|
||||
@ -770,23 +680,17 @@ func (q *Queries) CreateAccount(ctx context.Context, arg CreateAccountParams) (A
|
||||
|
||||
const createAmoAccount = `-- name: CreateAmoAccount :exec
|
||||
|
||||
INSERT INTO users (AccountID, AmoID, Name, Email, Role, "Group", Deleted, CreatedAt, Subdomain, AmoUserID, Country,DriveURL)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
||||
INSERT INTO accountsAmo (AccountID, AmoID,Name, Subdomain, Country,DriveURL)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
`
|
||||
|
||||
type CreateAmoAccountParams struct {
|
||||
Accountid string `db:"accountid" json:"accountid"`
|
||||
Amoid int32 `db:"amoid" json:"amoid"`
|
||||
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 sql.NullTime `db:"createdat" json:"createdat"`
|
||||
Subdomain string `db:"subdomain" json:"subdomain"`
|
||||
Amouserid int32 `db:"amouserid" json:"amouserid"`
|
||||
Country string `db:"country" json:"country"`
|
||||
Driveurl string `db:"driveurl" json:"driveurl"`
|
||||
Accountid string `db:"accountid" json:"accountid"`
|
||||
Amoid int32 `db:"amoid" json:"amoid"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Subdomain string `db:"subdomain" json:"subdomain"`
|
||||
Country string `db:"country" json:"country"`
|
||||
Driveurl string `db:"driveurl" json:"driveurl"`
|
||||
}
|
||||
|
||||
// amo methods:
|
||||
@ -795,13 +699,7 @@ func (q *Queries) CreateAmoAccount(ctx context.Context, arg CreateAmoAccountPara
|
||||
arg.Accountid,
|
||||
arg.Amoid,
|
||||
arg.Name,
|
||||
arg.Email,
|
||||
arg.Role,
|
||||
arg.Group,
|
||||
arg.Deleted,
|
||||
arg.Createdat,
|
||||
arg.Subdomain,
|
||||
arg.Amouserid,
|
||||
arg.Country,
|
||||
arg.Driveurl,
|
||||
)
|
||||
@ -1034,7 +932,7 @@ func (q *Queries) DeleteTags(ctx context.Context, dollar_1 []int64) error {
|
||||
}
|
||||
|
||||
const deleteUsers = `-- name: DeleteUsers :exec
|
||||
UPDATE users SET Deleted = true WHERE ID = ANY($1::bigint[])
|
||||
UPDATE usersAmo SET Deleted = true WHERE ID = ANY($1::bigint[])
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteUsers(ctx context.Context, dollar_1 []int64) error {
|
||||
@ -1486,6 +1384,43 @@ func (q *Queries) GetAllAnswersByQuizID(ctx context.Context, session sql.NullStr
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getAllCompanyUsers = `-- name: GetAllCompanyUsers :many
|
||||
SELECT id, amoid, amouserid, name, email, role, "Group", deleted, createdat FROM usersamo WHERE amoid = $1 AND deleted = false
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllCompanyUsers(ctx context.Context, amoid int32) ([]Usersamo, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getAllCompanyUsers, amoid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Usersamo
|
||||
for rows.Next() {
|
||||
var i Usersamo
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Amoid,
|
||||
&i.Amouserid,
|
||||
&i.Name,
|
||||
&i.Email,
|
||||
&i.Role,
|
||||
&i.Group,
|
||||
&i.Deleted,
|
||||
&i.Createdat,
|
||||
); 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 getAllTokens = `-- name: GetAllTokens :many
|
||||
SELECT accountid, refreshtoken, accesstoken, authcode, expiration, createdat FROM tokens
|
||||
`
|
||||
@ -1520,31 +1455,67 @@ func (q *Queries) GetAllTokens(ctx context.Context) ([]Token, error) {
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getCurrentAccount = `-- name: GetCurrentAccount :one
|
||||
SELECT id, accountid, amoid, name, email, role, "Group", deleted, createdat, subdomain, amouserid, country, driveurl FROM users WHERE AccountID = $1 AND Deleted = false
|
||||
const getCurrentCompany = `-- name: GetCurrentCompany :one
|
||||
SELECT id, accountid, amoid, name, deleted, createdat, subdomain, country, driveurl FROM accountsAmo WHERE AccountID = $1 AND Deleted = false
|
||||
`
|
||||
|
||||
func (q *Queries) GetCurrentAccount(ctx context.Context, accountid string) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, getCurrentAccount, accountid)
|
||||
var i User
|
||||
func (q *Queries) GetCurrentCompany(ctx context.Context, accountid string) (Accountsamo, error) {
|
||||
row := q.db.QueryRowContext(ctx, getCurrentCompany, accountid)
|
||||
var i Accountsamo
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Accountid,
|
||||
&i.Amoid,
|
||||
&i.Name,
|
||||
&i.Email,
|
||||
&i.Role,
|
||||
&i.Group,
|
||||
&i.Deleted,
|
||||
&i.Createdat,
|
||||
&i.Subdomain,
|
||||
&i.Amouserid,
|
||||
&i.Country,
|
||||
&i.Driveurl,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getExistingContactAmo = `-- name: GetExistingContactAmo :many
|
||||
WITH getAmoID AS (
|
||||
SELECT AmoID FROM amoContact WHERE amoContact.AccountID = $1 AND amoContact.Field = ANY($2::text[])
|
||||
) SELECT id, accountid, amoid, field FROM amoContact
|
||||
WHERE amoContact.AccountID = $1 AND amoContact.AmoID IN (SELECT AmoID FROM getAmoID)
|
||||
`
|
||||
|
||||
type GetExistingContactAmoParams struct {
|
||||
Accountid int32 `db:"accountid" json:"accountid"`
|
||||
Column2 []string `db:"column_2" json:"column_2"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetExistingContactAmo(ctx context.Context, arg GetExistingContactAmoParams) ([]Amocontact, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getExistingContactAmo, arg.Accountid, pq.Array(arg.Column2))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Amocontact
|
||||
for rows.Next() {
|
||||
var i Amocontact
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Accountid,
|
||||
&i.Amoid,
|
||||
&i.Field,
|
||||
); 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 getExpiredCountPrivilege = `-- name: GetExpiredCountPrivilege :many
|
||||
SELECT p.id, p.privilegeID, p.privilege_name, p.amount, p.created_at, a.user_id
|
||||
FROM privileges p
|
||||
@ -1661,8 +1632,11 @@ func (q *Queries) GetFieldByAmoID(ctx context.Context, amoid int32) (Field, erro
|
||||
}
|
||||
|
||||
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
|
||||
FROM fields f JOIN (SELECT AmoID FROM users WHERE users.AccountID = $1 AND Deleted = false) u ON f.AccountID = u.AmoID
|
||||
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
|
||||
`
|
||||
@ -1817,8 +1791,11 @@ func (q *Queries) GetListStartQuiz(ctx context.Context, accountid string) ([]int
|
||||
}
|
||||
|
||||
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
|
||||
FROM pipelines p JOIN (SELECT AmoID FROM users WHERE users.AccountID = $1 AND Deleted = false) u ON p.AccountID = u.AmoID
|
||||
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
|
||||
`
|
||||
@ -2432,8 +2409,11 @@ func (q *Queries) GetResultAnswers(ctx context.Context, id int64) ([]GetResultAn
|
||||
}
|
||||
|
||||
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
|
||||
FROM steps s JOIN (SELECT AmoID FROM users WHERE users.AccountID = $1 AND Deleted = false) u ON s.AccountID = u.AmoID
|
||||
FROM steps s JOIN user_data u ON s.AccountID = u.AmoID
|
||||
WHERE s.Deleted = false AND PipelineID = $4
|
||||
ORDER BY s.ID OFFSET ($2 - 1) * $3 LIMIT $3
|
||||
`
|
||||
@ -2496,8 +2476,11 @@ func (q *Queries) GetStepsWithPagination(ctx context.Context, arg GetStepsWithPa
|
||||
}
|
||||
|
||||
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
|
||||
FROM tags t JOIN (SELECT AmoID FROM users WHERE users.AccountID = $1 AND Deleted = false) u ON t.AccountID = u.AmoID
|
||||
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
|
||||
`
|
||||
@ -2752,44 +2735,28 @@ func (q *Queries) GetUserTagsByID(ctx context.Context, accountid int32) ([]GetUs
|
||||
}
|
||||
|
||||
const getUserUsersByID = `-- name: GetUserUsersByID :many
|
||||
SELECT ID,AccountID,AmoID,Name,Email,Role,"Group",Subdomain,AmoUserID,Country
|
||||
FROM users
|
||||
WHERE AmoUserID = $1 AND Deleted = false
|
||||
SELECT id, amoid, amouserid, name, email, role, "Group", deleted, createdat FROM usersAmo WHERE amoid = $1 AND Deleted = false
|
||||
`
|
||||
|
||||
type GetUserUsersByIDRow 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"`
|
||||
Email string `db:"email" json:"email"`
|
||||
Role int32 `db:"role" json:"role"`
|
||||
Group int32 `db:"Group" json:"Group"`
|
||||
Subdomain string `db:"subdomain" json:"subdomain"`
|
||||
Amouserid int32 `db:"amouserid" json:"amouserid"`
|
||||
Country string `db:"country" json:"country"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetUserUsersByID(ctx context.Context, amouserid int32) ([]GetUserUsersByIDRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getUserUsersByID, amouserid)
|
||||
func (q *Queries) GetUserUsersByID(ctx context.Context, amoid int32) ([]Usersamo, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getUserUsersByID, amoid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetUserUsersByIDRow
|
||||
var items []Usersamo
|
||||
for rows.Next() {
|
||||
var i GetUserUsersByIDRow
|
||||
var i Usersamo
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Accountid,
|
||||
&i.Amoid,
|
||||
&i.Amouserid,
|
||||
&i.Name,
|
||||
&i.Email,
|
||||
&i.Role,
|
||||
&i.Group,
|
||||
&i.Subdomain,
|
||||
&i.Amouserid,
|
||||
&i.Country,
|
||||
&i.Deleted,
|
||||
&i.Createdat,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -2806,11 +2773,11 @@ func (q *Queries) GetUserUsersByID(ctx context.Context, amouserid int32) ([]GetU
|
||||
|
||||
const getUsersWithPagination = `-- name: GetUsersWithPagination :many
|
||||
WITH user_data AS (
|
||||
SELECT AmoID FROM users WHERE users.AccountID = $1 AND Deleted = false
|
||||
SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false
|
||||
)
|
||||
SELECT u.id, u.accountid, u.amoid, u.name, u.email, u.role, u."Group", u.deleted, u.createdat, u.subdomain, u.amouserid, u.country, u.driveurl, COUNT(*) OVER() as total_count
|
||||
FROM users u
|
||||
JOIN user_data a ON u.AmoUserID = a.AmoID
|
||||
SELECT u.id, u.amoid, u.amouserid, u.name, u.email, u.role, u."Group", u.deleted, u.createdat, COUNT(*) OVER() as total_count
|
||||
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
|
||||
`
|
||||
@ -2822,20 +2789,16 @@ type GetUsersWithPaginationParams struct {
|
||||
}
|
||||
|
||||
type GetUsersWithPaginationRow 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"`
|
||||
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 sql.NullTime `db:"createdat" json:"createdat"`
|
||||
Subdomain string `db:"subdomain" json:"subdomain"`
|
||||
Amouserid int32 `db:"amouserid" json:"amouserid"`
|
||||
Country string `db:"country" json:"country"`
|
||||
Driveurl string `db:"driveurl" json:"driveurl"`
|
||||
TotalCount int64 `db:"total_count" json:"total_count"`
|
||||
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) {
|
||||
@ -2849,18 +2812,14 @@ func (q *Queries) GetUsersWithPagination(ctx context.Context, arg GetUsersWithPa
|
||||
var i GetUsersWithPaginationRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Accountid,
|
||||
&i.Amoid,
|
||||
&i.Amouserid,
|
||||
&i.Name,
|
||||
&i.Email,
|
||||
&i.Role,
|
||||
&i.Group,
|
||||
&i.Deleted,
|
||||
&i.Createdat,
|
||||
&i.Subdomain,
|
||||
&i.Amouserid,
|
||||
&i.Country,
|
||||
&i.Driveurl,
|
||||
&i.TotalCount,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@ -2878,17 +2837,17 @@ 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,
|
||||
(SELECT a2.utm
|
||||
COALESCE((SELECT a2.utm
|
||||
FROM answer a2
|
||||
WHERE a2.start = true AND a2.session = a.session
|
||||
LIMIT 1) AS utm
|
||||
,t.accesstoken,r.accountid,r.fieldsrule,r.tagstoadd,r.performerid,r.stepid,r.pipelineid,(SELECT u.name FROM users u WHERE u.amoid = r.performerid) AS performer_name,u.subdomain,u.accountid,u.driveurl
|
||||
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
|
||||
FROM answer a
|
||||
INNER JOIN quiz q ON a.quiz_id = q.id
|
||||
LEFT JOIN amoCRMStatuses s ON a.id = s.AnswerID
|
||||
INNER JOIN rules r ON q.id = r.QuizID
|
||||
INNER JOIN tokens t ON q.accountid = t.AccountID
|
||||
INNER JOIN users u ON q.accountid = u.accountid AND u.amoid = r.accountid
|
||||
INNER JOIN accountsAmo u ON q.accountid = u.accountid AND u.amoid = r.accountid
|
||||
WHERE a.result = true
|
||||
AND s.id IS NULL
|
||||
AND a.deleted = false
|
||||
@ -2904,7 +2863,7 @@ type GettingAmoUsersTrueResultsRow struct {
|
||||
QuestionID int64 `db:"question_id" json:"question_id"`
|
||||
Content sql.NullString `db:"content" json:"content"`
|
||||
Session sql.NullString `db:"session" json:"session"`
|
||||
Utm json.RawMessage `db:"utm" json:"utm"`
|
||||
Utm interface{} `db:"utm" json:"utm"`
|
||||
Accesstoken string `db:"accesstoken" json:"accesstoken"`
|
||||
Accountid int32 `db:"accountid" json:"accountid"`
|
||||
Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"`
|
||||
@ -3038,6 +2997,23 @@ func (q *Queries) InsertAnswers(ctx context.Context, arg InsertAnswersParams) (A
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertContactAmo = `-- name: InsertContactAmo :one
|
||||
INSERT INTO amoContact (AccountID, AmoID, Field) VALUES ($1, $2, $3) RETURNING AmoID
|
||||
`
|
||||
|
||||
type InsertContactAmoParams struct {
|
||||
Accountid int32 `db:"accountid" json:"accountid"`
|
||||
Amoid int32 `db:"amoid" json:"amoid"`
|
||||
Field string `db:"field" json:"field"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertContactAmo(ctx context.Context, arg InsertContactAmoParams) (int32, error) {
|
||||
row := q.db.QueryRowContext(ctx, insertContactAmo, arg.Accountid, arg.Amoid, arg.Field)
|
||||
var amoid int32
|
||||
err := row.Scan(&amoid)
|
||||
return amoid, err
|
||||
}
|
||||
|
||||
const insertPrivilege = `-- name: InsertPrivilege :exec
|
||||
INSERT INTO privileges (privilegeID, account_id, privilege_name, amount, created_at) VALUES ($1, $2, $3, $4, $5)
|
||||
`
|
||||
@ -3439,7 +3415,7 @@ func (q *Queries) QuizCopyQid(ctx context.Context, arg QuizCopyQidParams) (QuizC
|
||||
const setQuizSettings = `-- name: SetQuizSettings :one
|
||||
INSERT INTO rules (AccountID, QuizID, PerformerID, PipelineID, StepID, FieldsRule,TagsToAdd)
|
||||
SELECT u.AmoID AS AccountID,$1 AS QuizID,$2 AS PerformerID,$3 AS PipelineID,
|
||||
$4 AS StepID,$5 AS FieldsRule,$6 AS TagsToAdd FROM users u WHERE u.AccountID = $7 AND u.Deleted = false
|
||||
$4 AS StepID,$5 AS FieldsRule,$6 AS TagsToAdd FROM accountsamo u WHERE u.AccountID = $7 AND u.Deleted = false
|
||||
RETURNING id
|
||||
`
|
||||
|
||||
@ -3472,7 +3448,7 @@ const settingDealAmoStatus = `-- name: SettingDealAmoStatus :exec
|
||||
INSERT INTO amoCRMStatuses (AccountID, DealID, AnswerID, Status)
|
||||
SELECT u.AmoID, $1, $2, $3
|
||||
FROM tokens AS t
|
||||
JOIN users AS u ON t.AccountID = u.AccountID
|
||||
JOIN accountsAmo AS u ON t.AccountID = u.AccountID
|
||||
WHERE t.AccessToken = $4 AND u.Deleted = false
|
||||
`
|
||||
|
||||
@ -3494,12 +3470,13 @@ func (q *Queries) SettingDealAmoStatus(ctx context.Context, arg SettingDealAmoSt
|
||||
}
|
||||
|
||||
const softDeleteAccount = `-- name: SoftDeleteAccount :exec
|
||||
WITH userd AS (
|
||||
SELECT AmoUserID FROM users WHERE users.AccountID = $1
|
||||
),
|
||||
tokend AS (
|
||||
UPDATE users SET Deleted = true WHERE AmoUserID IN (SELECT AmoUserID FROM userd)
|
||||
)
|
||||
WITH amoCompany AS (
|
||||
SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1
|
||||
),usersDel AS (
|
||||
UPDATE usersAmo SET Deleted = true WHERE AmoID = (SELECT AmoID FROM amoCompany)
|
||||
),
|
||||
companyDel AS ( UPDATE accountsAmo SET Deleted = true WHERE AmoID = (SELECT AmoID FROM amoCompany)
|
||||
)
|
||||
DELETE FROM tokens WHERE tokens.AccountID = $1
|
||||
`
|
||||
|
||||
@ -3545,9 +3522,73 @@ func (q *Queries) TemplateCopy(ctx context.Context, arg TemplateCopyParams) (int
|
||||
return quiz_id, err
|
||||
}
|
||||
|
||||
const updateAmoAccount = `-- name: UpdateAmoAccount :exec
|
||||
UPDATE accountsAmo SET Name = $2, Subdomain = $3, Country = $4, DriveURL = $5 WHERE AccountID = $1 AND Deleted = false
|
||||
`
|
||||
|
||||
type UpdateAmoAccountParams struct {
|
||||
Accountid string `db:"accountid" json:"accountid"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Subdomain string `db:"subdomain" json:"subdomain"`
|
||||
Country string `db:"country" json:"country"`
|
||||
Driveurl string `db:"driveurl" json:"driveurl"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateAmoAccount(ctx context.Context, arg UpdateAmoAccountParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateAmoAccount,
|
||||
arg.Accountid,
|
||||
arg.Name,
|
||||
arg.Subdomain,
|
||||
arg.Country,
|
||||
arg.Driveurl,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateAmoAccountUser = `-- name: UpdateAmoAccountUser :exec
|
||||
UPDATE usersAmo SET Name = $3, Email = $4, Role = $5, "Group" = $6
|
||||
WHERE AmoID = $1 AND AmoUserID = $2 AND deleted = false
|
||||
`
|
||||
|
||||
type UpdateAmoAccountUserParams struct {
|
||||
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"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateAmoAccountUser(ctx context.Context, arg UpdateAmoAccountUserParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateAmoAccountUser,
|
||||
arg.Amoid,
|
||||
arg.Amouserid,
|
||||
arg.Name,
|
||||
arg.Email,
|
||||
arg.Role,
|
||||
arg.Group,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateAmoContact = `-- name: UpdateAmoContact :exec
|
||||
UPDATE amoContact SET Field = $1,AmoID=$3 WHERE ID = $2
|
||||
`
|
||||
|
||||
type UpdateAmoContactParams struct {
|
||||
Field string `db:"field" json:"field"`
|
||||
ID int64 `db:"id" json:"id"`
|
||||
Amoid int32 `db:"amoid" json:"amoid"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateAmoContact(ctx context.Context, arg UpdateAmoContactParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateAmoContact, arg.Field, arg.ID, arg.Amoid)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateFieldRules = `-- name: UpdateFieldRules :exec
|
||||
UPDATE rules SET FieldsRule = $1
|
||||
WHERE AccountID = (SELECT AmoID FROM users WHERE users.AccountID = $2 AND users.Deleted = false) AND QuizID = $3 AND Deleted = false
|
||||
WHERE AccountID = (SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $2 AND accountsAmo.Deleted = false) AND QuizID = $3 AND Deleted = false
|
||||
`
|
||||
|
||||
type UpdateFieldRulesParams struct {
|
||||
@ -3680,25 +3721,9 @@ func (q *Queries) UpdateTags(ctx context.Context, dollar_1 json.RawMessage) erro
|
||||
return err
|
||||
}
|
||||
|
||||
const updateUsers = `-- name: UpdateUsers :exec
|
||||
UPDATE users AS u
|
||||
SET Name = (update_data ->> 'Name')::varchar(512),
|
||||
Email = (update_data ->> 'Email')::varchar(50),
|
||||
Role = (update_data ->> 'Role')::INT,
|
||||
"Group" = (update_data ->> 'Group')::INT,
|
||||
AmoUserID= (update_data ->> 'AmoUserID')::INT
|
||||
FROM json_array_elements($1::json) AS update_data
|
||||
WHERE u.AmoID = (update_data ->> 'AmocrmID')::INT
|
||||
`
|
||||
|
||||
func (q *Queries) UpdateUsers(ctx context.Context, dollar_1 json.RawMessage) error {
|
||||
_, err := q.db.ExecContext(ctx, updateUsers, dollar_1)
|
||||
return err
|
||||
}
|
||||
|
||||
const updatingDealAmoStatus = `-- name: UpdatingDealAmoStatus :exec
|
||||
UPDATE amoCRMStatuses SET Status = $1
|
||||
WHERE DealID = $2 AND AccountID = (SELECT u.AmoID FROM tokens AS t JOIN users AS u ON t.AccountID = u.AccountID WHERE t.AccessToken = $3 AND u.Deleted = false)
|
||||
WHERE DealID = $2 AND AccountID = (SELECT u.AmoID FROM tokens AS t JOIN accountsAmo AS u ON t.AccountID = u.AccountID WHERE t.AccessToken = $3 AND u.Deleted = false)
|
||||
`
|
||||
|
||||
type UpdatingDealAmoStatusParams struct {
|
||||
@ -3713,14 +3738,17 @@ func (q *Queries) UpdatingDealAmoStatus(ctx context.Context, arg UpdatingDealAmo
|
||||
}
|
||||
|
||||
const webhookDelete = `-- name: WebhookDelete :exec
|
||||
WITH userd AS (
|
||||
UPDATE users SET Deleted = true WHERE AmoUserID = $1 RETURNING AccountID
|
||||
WITH companyDel AS (
|
||||
UPDATE accountsAmo SET Deleted = true WHERE accountsAmo.AmoID = $1 RETURNING AccountID
|
||||
),
|
||||
userDel AS (
|
||||
UPDATE usersAmo SET Deleted = true WHERE AmoID = $1
|
||||
)
|
||||
DELETE FROM tokens WHERE AccountID IN (SELECT AccountID FROM userd)
|
||||
DELETE FROM tokens WHERE AccountID IN (SELECT AccountID FROM companyDel)
|
||||
`
|
||||
|
||||
func (q *Queries) WebhookDelete(ctx context.Context, amouserid int32) error {
|
||||
_, err := q.db.ExecContext(ctx, webhookDelete, amouserid)
|
||||
func (q *Queries) WebhookDelete(ctx context.Context, amoid int32) error {
|
||||
_, err := q.db.ExecContext(ctx, webhookDelete, amoid)
|
||||
return err
|
||||
}
|
||||
|
||||
|
2
go.mod
2
go.mod
@ -3,6 +3,7 @@ module penahub.gitlab.yandexcloud.net/backend/quiz/common.git
|
||||
go 1.21.4
|
||||
|
||||
require (
|
||||
github.com/ClickHouse/clickhouse-go v1.5.4
|
||||
github.com/gofiber/fiber/v2 v2.52.0
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0
|
||||
github.com/golang/protobuf v1.5.3
|
||||
@ -19,6 +20,7 @@ require (
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
|
12
go.sum
12
go.sum
@ -1,12 +1,19 @@
|
||||
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/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/bkaradzic/go-lz4 v1.0.0 h1:RXc4wYsyz985CkXXeX04y4VnZFGG8Rd43pRaHsOXAKk=
|
||||
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
|
||||
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/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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/gofiber/fiber/v2 v2.52.0 h1:S+qXi7y+/Pgvqq4DrSmREGiFwtB7Bu6+QFLuIHYw/UE=
|
||||
github.com/gofiber/fiber/v2 v2.52.0/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
||||
@ -20,6 +27,7 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
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/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
|
||||
@ -32,6 +40,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
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/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
@ -41,6 +50,7 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
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.69 h1:l8AnsQFyY1xiwa/DaQskY4NXSLA2yrGsW5iD9nRPVS0=
|
||||
@ -52,6 +62,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
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/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=
|
||||
|
60
model/amo.go
60
model/amo.go
@ -1,32 +1,30 @@
|
||||
package model
|
||||
|
||||
type User struct {
|
||||
/* - айдишник в нашей системе Primary Key*/
|
||||
ID int64 `json:"ID"`
|
||||
/* - id пользователя из токена в нашей системе*/
|
||||
Accountid string `json:"AccountID"`
|
||||
/* - айдишник пользователя в амо*/
|
||||
AmoID int32 `json:"AmocrmID"`
|
||||
/* - имя аккаунта в амо*/
|
||||
Name string `json:"Name"`
|
||||
/* - почта пользователя из амо*/
|
||||
Email string `json:"Email"`
|
||||
/* - роль пользователя в амо*/
|
||||
Role int32 `json:"Role"`
|
||||
/* - группы пользователя в амо*/
|
||||
Group int32 `json:"Group"`
|
||||
/* - флаг мягкого удаления*/
|
||||
Deleted bool `json:"Deleted"`
|
||||
/* - таймштамп создания аккаунта*/
|
||||
Createdat int64 `json:"CreatedAt"`
|
||||
/* - поддомен организации в амо*/
|
||||
Subdomain string `json:"Subdomain"`
|
||||
/* - айдишник пользвателя, который подключал интеграцию*/
|
||||
Amouserid int32 `json:"AmoUserID"`
|
||||
/* - страна указанная в настройках амо*/
|
||||
Country string `json:"Country"`
|
||||
// урл объектного хранилища пользователя в амо
|
||||
DriveURL string `json:"DriveURL"`
|
||||
import "time"
|
||||
|
||||
type AmoAccountUser struct {
|
||||
ID int64 `json:"id"` // ID пользователя
|
||||
AmoID int32 `json:"amoID"` // ID компании в амо, к которой пользователь принадлежит
|
||||
AmoUserID int32 `json:"amoUserID"` // ID пользователя в амо
|
||||
Name string `json:"name"` // Имя
|
||||
Email string `json:"email"` // Email
|
||||
Role int32 `json:"role"` // Роль
|
||||
Group int32 `json:"group"` // Группа
|
||||
Deleted bool `json:"deleted"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
|
||||
type AmoAccount struct {
|
||||
ID int64 `json:"id"` // ID компании
|
||||
AccountID string `json:"accountID"` // ID аккаунта нас
|
||||
AmoID int32 `json:"amoID"` // ID компании в амо
|
||||
Name string `json:"name"` // Название
|
||||
Deleted bool `json:"deleted"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
Subdomain string `json:"subdomain"` // поддомен
|
||||
Country string `json:"country"` // Страна
|
||||
DriveURL string `json:"driveURL"` // URL объктного хранилища
|
||||
Stale bool `json:"stale"` // флаг "не свежести" если с токенами все в порядке - false, если просрочились то true
|
||||
}
|
||||
|
||||
type UserGroups struct {
|
||||
@ -290,3 +288,11 @@ type AmoUsersTrueResults struct {
|
||||
QuizAccountID string
|
||||
DriveURL string
|
||||
}
|
||||
|
||||
// возможно стоит добавить enum? тип ContactQuizConfig уже есть
|
||||
type ContactAmo struct {
|
||||
ID int64
|
||||
AccountID int32 // id аккаунта в амо к которому привязан контакт
|
||||
AmoID int32 // id контакта в амо
|
||||
Field string // значение поля
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ type UserListResp struct {
|
||||
/* - общее количество юзеров, которые у нас закешированы для этого пользователя*/
|
||||
Count int64 `json:"count"`
|
||||
/* - список юзеров, которые были закешированы нашим сервисом*/
|
||||
Items []User `json:"items"`
|
||||
Items []AmoAccountUser `json:"items"`
|
||||
}
|
||||
|
||||
type UserListStepsResp struct {
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"encoding/json"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/dal/sqlcgen"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/model"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/pj_errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -39,20 +40,18 @@ func (r *AmoRepository) GettingUserWithPagination(ctx context.Context, req *mode
|
||||
return nil, err
|
||||
}
|
||||
var count int64
|
||||
var users []model.User
|
||||
var users []model.AmoAccountUser
|
||||
for _, row := range rows {
|
||||
user := model.User{
|
||||
user := model.AmoAccountUser{
|
||||
ID: row.ID,
|
||||
Accountid: row.Accountid,
|
||||
AmoID: row.Amoid,
|
||||
AmoUserID: row.Amouserid,
|
||||
Name: row.Name,
|
||||
Email: row.Email,
|
||||
Group: row.Group,
|
||||
Role: row.Role,
|
||||
Createdat: row.Createdat.Time.Unix(),
|
||||
Subdomain: row.Subdomain,
|
||||
Amouserid: row.Amouserid,
|
||||
Country: row.Country,
|
||||
Deleted: row.Deleted,
|
||||
CreatedAt: row.Createdat,
|
||||
}
|
||||
count = row.TotalCount
|
||||
|
||||
@ -75,41 +74,58 @@ func (r *AmoRepository) SoftDeleteAccount(ctx context.Context, accountID string)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *AmoRepository) GetCurrentAccount(ctx context.Context, accountID string) (*model.User, error) {
|
||||
row, err := r.queries.GetCurrentAccount(ctx, accountID)
|
||||
func (r *AmoRepository) GetCurrentAccount(ctx context.Context, accountID string) (*model.AmoAccount, error) {
|
||||
row, err := r.queries.GetCurrentCompany(ctx, accountID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user := model.User{
|
||||
user := model.AmoAccount{
|
||||
ID: row.ID,
|
||||
Accountid: row.Accountid,
|
||||
AccountID: row.Accountid,
|
||||
AmoID: row.Amoid,
|
||||
Name: row.Name,
|
||||
Email: row.Email,
|
||||
Role: row.Role,
|
||||
Group: row.Group,
|
||||
Createdat: row.Createdat.Time.Unix(),
|
||||
Deleted: row.Deleted,
|
||||
CreatedAt: row.Createdat,
|
||||
Subdomain: row.Subdomain,
|
||||
Amouserid: row.Amouserid,
|
||||
Country: row.Country,
|
||||
DriveURL: row.Driveurl,
|
||||
}
|
||||
|
||||
_, err = r.queries.CheckExpiredToken(ctx, accountID)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
user.Stale = false
|
||||
return &user, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user.Stale = true
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (r *AmoRepository) CreateAccount(ctx context.Context, accountID string, userInfo model.User) error {
|
||||
func (r *AmoRepository) UpdateCurrentAccount(ctx context.Context, user model.AmoAccount) error {
|
||||
err := r.queries.UpdateAmoAccount(ctx, sqlcgen.UpdateAmoAccountParams{
|
||||
Accountid: user.AccountID,
|
||||
Name: user.Name,
|
||||
Subdomain: user.Subdomain,
|
||||
Country: user.Country,
|
||||
Driveurl: user.DriveURL,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *AmoRepository) CreateAccount(ctx context.Context, userInfo model.AmoAccount) error {
|
||||
err := r.queries.CreateAmoAccount(ctx, sqlcgen.CreateAmoAccountParams{
|
||||
Accountid: accountID,
|
||||
Accountid: userInfo.AccountID,
|
||||
Amoid: userInfo.AmoID,
|
||||
Name: userInfo.Name,
|
||||
Email: userInfo.Email,
|
||||
Role: userInfo.Role,
|
||||
Group: userInfo.Group,
|
||||
Createdat: sql.NullTime{Time: time.Now(), Valid: true},
|
||||
Subdomain: userInfo.Subdomain,
|
||||
Amouserid: userInfo.Amouserid,
|
||||
Country: userInfo.Country,
|
||||
Driveurl: userInfo.DriveURL,
|
||||
})
|
||||
@ -121,15 +137,17 @@ func (r *AmoRepository) CreateAccount(ctx context.Context, accountID string, use
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *AmoRepository) CheckMainUser(ctx context.Context, user model.User) error {
|
||||
err := r.queries.CheckMainUser(ctx, sqlcgen.CheckMainUserParams{
|
||||
Name: user.Name,
|
||||
Group: user.Group,
|
||||
Email: user.Email,
|
||||
Role: user.Role,
|
||||
Amoid: user.AmoID,
|
||||
})
|
||||
// todo возможно стоит обновлять еще и компанию пока не знаю
|
||||
|
||||
func (r *AmoRepository) AddAmoAccountUser(ctx context.Context, user model.AmoAccountUser) error {
|
||||
err := r.queries.AddAmoAccountUser(ctx, sqlcgen.AddAmoAccountUserParams{
|
||||
Amoid: user.AmoID,
|
||||
Amouserid: user.AmoUserID,
|
||||
Name: user.Name,
|
||||
Email: user.Email,
|
||||
Role: user.Role,
|
||||
Group: user.Group,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -137,39 +155,18 @@ func (r *AmoRepository) CheckMainUser(ctx context.Context, user model.User) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *AmoRepository) CheckAndUpdateUsers(ctx context.Context, users []model.User) error {
|
||||
dollar1, err := json.Marshal(users)
|
||||
func (r *AmoRepository) UpdateAmoAccountUser(ctx context.Context, user model.AmoAccountUser) error {
|
||||
err := r.queries.UpdateAmoAccountUser(ctx, sqlcgen.UpdateAmoAccountUserParams{
|
||||
Amoid: user.AmoID,
|
||||
Amouserid: user.AmoUserID,
|
||||
Name: user.Name,
|
||||
Email: user.Email,
|
||||
Role: user.Role,
|
||||
Group: user.Group,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rows, err := r.queries.CheckUsers(ctx, dollar1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if rows != nil {
|
||||
var toUpdate []model.User
|
||||
for _, row := range rows {
|
||||
to := model.User{
|
||||
AmoID: row.Amoid,
|
||||
Name: row.Name,
|
||||
Group: row.Group,
|
||||
Role: row.Role,
|
||||
Email: row.Email,
|
||||
Amouserid: row.Amouserid,
|
||||
}
|
||||
toUpdate = append(toUpdate, to)
|
||||
}
|
||||
dollar1, err := json.Marshal(toUpdate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = r.queries.UpdateUsers(ctx, dollar1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -195,27 +192,25 @@ func (r *AmoRepository) DeleteUsers(ctx context.Context, ids []int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *AmoRepository) GetUserUsersByID(ctx context.Context, amoUserID int32) ([]model.User, error) {
|
||||
func (r *AmoRepository) GetUserUsersByID(ctx context.Context, amoUserID int32) ([]model.AmoAccountUser, error) {
|
||||
rows, err := r.queries.GetUserUsersByID(ctx, amoUserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var users []model.User
|
||||
var users []model.AmoAccountUser
|
||||
for _, row := range rows {
|
||||
user := model.User{
|
||||
user := model.AmoAccountUser{
|
||||
ID: row.ID,
|
||||
Accountid: row.Accountid,
|
||||
AmoID: row.Amoid,
|
||||
AmoUserID: row.Amouserid,
|
||||
Name: row.Name,
|
||||
Email: row.Email,
|
||||
Group: row.Group,
|
||||
Role: row.Role,
|
||||
Subdomain: row.Subdomain,
|
||||
Amouserid: row.Amouserid,
|
||||
Country: row.Country,
|
||||
Deleted: row.Deleted,
|
||||
CreatedAt: row.Createdat,
|
||||
}
|
||||
|
||||
users = append(users, user)
|
||||
}
|
||||
|
||||
@ -256,31 +251,6 @@ func (r *AmoRepository) WebhookUpdate(ctx context.Context, token model.Token) er
|
||||
return nil
|
||||
}
|
||||
|
||||
// воркер запускается каждые 5 минут, поэтомму ищем токены котторые исекают менее чем через 10 минут отдаем их на обноление
|
||||
func (r *AmoRepository) CheckExpired(ctx context.Context) ([]model.Token, error) {
|
||||
rows, err := r.queries.CheckExpired(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tokens []model.Token
|
||||
|
||||
for _, row := range rows {
|
||||
token := model.Token{
|
||||
AccountID: row.Accountid,
|
||||
AccessToken: row.Accesstoken,
|
||||
RefreshToken: row.Refreshtoken,
|
||||
AuthCode: row.Authcode,
|
||||
Expiration: row.Expiration.Unix(),
|
||||
CreatedAt: row.Createdat.Time.Unix(),
|
||||
}
|
||||
|
||||
tokens = append(tokens, token)
|
||||
}
|
||||
|
||||
return tokens, nil
|
||||
}
|
||||
|
||||
func (r *AmoRepository) GetAllTokens(ctx context.Context) ([]model.Token, error) {
|
||||
rows, err := r.queries.GetAllTokens(ctx)
|
||||
if err != nil {
|
||||
@ -1038,7 +1008,7 @@ func (r *AmoRepository) GettingAmoUsersTrueResults(ctx context.Context) ([]model
|
||||
}
|
||||
|
||||
var utm model.UTMSavingMap
|
||||
err = json.Unmarshal(row.Utm, &utm)
|
||||
err = json.Unmarshal(row.Utm.([]byte), &utm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1111,3 +1081,60 @@ func (r *AmoRepository) UpdatingDealAmoStatus(ctx context.Context, deps SaveDeal
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// методы для contact в амо
|
||||
|
||||
func (r *AmoRepository) GetExistingContactAmo(ctx context.Context, accountID int32, fields []string) (map[int32][]model.ContactAmo, error) {
|
||||
rows, err := r.queries.GetExistingContactAmo(ctx, sqlcgen.GetExistingContactAmoParams{
|
||||
Accountid: accountID,
|
||||
Column2: fields,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, pj_errors.ErrNotFound
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[int32][]model.ContactAmo)
|
||||
|
||||
for _, row := range rows {
|
||||
result[row.Amoid] = append(result[row.Amoid], model.ContactAmo{
|
||||
ID: row.ID,
|
||||
AmoID: row.Amoid,
|
||||
AccountID: row.Accountid,
|
||||
Field: row.Field,
|
||||
})
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *AmoRepository) InsertContactAmo(ctx context.Context, val model.ContactAmo) (int32, error) {
|
||||
amoID, err := r.queries.InsertContactAmo(ctx, sqlcgen.InsertContactAmoParams{
|
||||
Accountid: val.AccountID,
|
||||
Amoid: val.AmoID,
|
||||
Field: val.Field,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return amoID, err
|
||||
}
|
||||
|
||||
func (r *AmoRepository) UpdateAmoContact(ctx context.Context, id int64, field string, newAmoID int32) error {
|
||||
err := r.queries.UpdateAmoContact(ctx, sqlcgen.UpdateAmoContactParams{
|
||||
Field: field,
|
||||
ID: id,
|
||||
Amoid: newAmoID,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -15,16 +15,14 @@ type Deps struct {
|
||||
}
|
||||
|
||||
type AnswerRepository struct {
|
||||
queries *sqlcgen.Queries
|
||||
pool *sql.DB
|
||||
answerMinio *StorerAnswer
|
||||
queries *sqlcgen.Queries
|
||||
pool *sql.DB
|
||||
}
|
||||
|
||||
func NewAnswerRepository(deps Deps) *AnswerRepository {
|
||||
return &AnswerRepository{
|
||||
queries: deps.Queries,
|
||||
pool: deps.Pool,
|
||||
answerMinio: deps.AnswerMinio,
|
||||
queries: deps.Queries,
|
||||
pool: deps.Pool,
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,17 +109,6 @@ func (r *AnswerRepository) GetAllAnswersByQuizID(ctx context.Context, session st
|
||||
}
|
||||
|
||||
for _, row := range rows {
|
||||
//todo тут забыл добавить проверку на то что minio !=nil
|
||||
/*if row.Questiontype == model.TypeFile {
|
||||
fmt.Println("GALL", row.Qid, row.QuestionID, row.Content)
|
||||
fileURL, err := r.answerMinio.GetAnswerURL(ctx, row.Qid.UUID.String(), row.QuestionID, row.Content.String)
|
||||
if err != nil {
|
||||
fmt.Println("GetAnswerURL dal answer minio answer", err)
|
||||
return nil, err
|
||||
}
|
||||
row.Content = sql.NullString{String: fmt.Sprintf("%s|%s", fileURL, row.Content.String), Valid: true}
|
||||
}*/
|
||||
|
||||
resultAnswer := model.ResultAnswer{
|
||||
Content: row.Content.String,
|
||||
CreatedAt: row.CreatedAt.Time,
|
||||
|
55
repository/answer/worker_answer.go
Normal file
55
repository/answer/worker_answer.go
Normal file
@ -0,0 +1,55 @@
|
||||
package answer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/dal/sqlcgen"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/model"
|
||||
)
|
||||
|
||||
type WorkerAnswerRepository struct {
|
||||
queries *sqlcgen.Queries
|
||||
pool *sql.DB
|
||||
answerMinio *StorerAnswer
|
||||
}
|
||||
|
||||
func NewWorkerAnswerRepo(deps Deps) *WorkerAnswerRepository {
|
||||
return &WorkerAnswerRepository{
|
||||
queries: deps.Queries,
|
||||
pool: deps.Pool,
|
||||
answerMinio: deps.AnswerMinio,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *WorkerAnswerRepository) GetAllAnswersByQuizID(ctx context.Context, session string) ([]model.ResultAnswer, error) {
|
||||
var results []model.ResultAnswer
|
||||
|
||||
rows, err := r.queries.GetAllAnswersByQuizID(ctx, sql.NullString{String: session, Valid: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, row := range rows {
|
||||
if row.Questiontype == model.TypeFile && r.answerMinio != nil {
|
||||
fmt.Println("GALL", row.Qid, row.QuestionID, row.Content)
|
||||
fileURL, err := r.answerMinio.GetAnswerURL(ctx, row.Qid.UUID.String(), row.QuestionID, row.Content.String)
|
||||
if err != nil {
|
||||
fmt.Println("GetAnswerURL dal answer minio answer", err)
|
||||
return nil, err
|
||||
}
|
||||
row.Content = sql.NullString{String: fmt.Sprintf("%s|%s", fileURL, row.Content.String), Valid: true}
|
||||
}
|
||||
|
||||
resultAnswer := model.ResultAnswer{
|
||||
Content: row.Content.String,
|
||||
CreatedAt: row.CreatedAt.Time,
|
||||
QuestionID: uint64(row.QuestionID),
|
||||
AnswerID: uint64(row.ID),
|
||||
}
|
||||
|
||||
results = append(results, resultAnswer)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
199
repository/statistics/click_statistics.go
Normal file
199
repository/statistics/click_statistics.go
Normal file
@ -0,0 +1,199 @@
|
||||
package statistics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/utils"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type DepsClick struct {
|
||||
Conn *sql.DB
|
||||
}
|
||||
|
||||
type StatisticClick struct {
|
||||
conn *sql.DB
|
||||
}
|
||||
|
||||
func NewClickStatistic(ctx context.Context, deps DepsClick) (*StatisticClick, error) {
|
||||
s := &StatisticClick{
|
||||
conn: deps.Conn,
|
||||
}
|
||||
|
||||
err := s.checkMW(ctx)
|
||||
if err != nil {
|
||||
fmt.Println("error check material view existing", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *StatisticClick) checkMW(ctx context.Context) error {
|
||||
query := `
|
||||
CREATE MATERIALIZED VIEW IF NOT EXISTS mv_last_answers_events
|
||||
ENGINE = MergeTree()
|
||||
ORDER BY (ctxsession, event_time) POPULATE AS
|
||||
SELECT
|
||||
event_time, ctxsession, ctxquizid, ctxquestionid, ctxidint, message,ctxquiz
|
||||
FROM statistics
|
||||
WHERE message IN ('InfoQuizOpen', 'InfoAnswer', 'InfoResult') AND event_level = 'info';
|
||||
`
|
||||
_, err := s.conn.ExecContext(ctx, query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Statistic struct {
|
||||
Count int64
|
||||
QuestionID int64
|
||||
}
|
||||
|
||||
type PipeLineStatsResp map[int64][]Statistic
|
||||
|
||||
// пример:
|
||||
//"[0, 116783, 116810]"
|
||||
//"[0, 116783, 116798]"
|
||||
//"[0, 116783, 116798, 116831]"
|
||||
//"[0, 116783, 116810, 116849]"
|
||||
//[0]
|
||||
//"[0, 116783]"
|
||||
//"[0, 116783, 116810, 116843]"
|
||||
|
||||
//SELECT DISTINCT last_que, reversed
|
||||
//FROM ( SELECT groupArray(ctxquestionid) AS reversed, arraySlice(arrayReverse(groupArray(ctxquestionid)), 1, 1)[1] AS last_que
|
||||
//FROM statistics WHERE ctxquizid = 26276 GROUP BY ctxsession ) AS sub;
|
||||
|
||||
func (s *StatisticClick) getFunnel(ctx context.Context, quizID int64, from uint64, to uint64) (map[int64][]int64, error) {
|
||||
query := `
|
||||
SELECT DISTINCT last_que, reversed
|
||||
FROM ( SELECT groupUniqArray(ctxquestionid) AS reversed, arraySlice(arrayReverse(groupArray(ctxquestionid)), 1, 1)[1] AS last_que
|
||||
FROM mv_last_answers_events WHERE ctxquizid = ? AND event_time BETWEEN ? AND ? GROUP BY ctxsession ) AS sub;
|
||||
`
|
||||
|
||||
rows, err := s.conn.QueryContext(ctx, query, quizID, from, to)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
funnel := make(map[int64][]int64)
|
||||
for rows.Next() {
|
||||
var lastQue int64
|
||||
var reversed []int64
|
||||
if err := rows.Scan(&lastQue, &reversed); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
funnel[lastQue] = reversed
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[int64][]int64)
|
||||
keys := make([]int64, 0, len(funnel))
|
||||
for key := range funnel {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
return keys[i] < keys[j]
|
||||
})
|
||||
|
||||
for _, lastQue := range keys {
|
||||
reversed := funnel[lastQue]
|
||||
found := false
|
||||
|
||||
for _, otherLastQue := range keys {
|
||||
if otherLastQue != lastQue {
|
||||
otherReversed := funnel[otherLastQue]
|
||||
sort.Slice(otherReversed, func(i, j int) bool {
|
||||
return otherReversed[i] < otherReversed[j]
|
||||
})
|
||||
index := utils.BinarySearch(lastQue, otherReversed)
|
||||
if index {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
result[lastQue] = reversed
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *StatisticClick) GetPipelinesStatistics(ctx context.Context, quizID int64, from uint64, to uint64) (PipeLineStatsResp, error) {
|
||||
pipelines := make(PipeLineStatsResp)
|
||||
|
||||
funnel, err := s.getFunnel(ctx, quizID, from, to)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for lastQue, idS := range funnel {
|
||||
sesCount, err := s.countSession(ctx, quizID, from, to, idS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, queID := range idS {
|
||||
if sessionCount, ok := sesCount[queID]; ok {
|
||||
pipeline := Statistic{
|
||||
QuestionID: queID,
|
||||
Count: sessionCount,
|
||||
}
|
||||
pipelines[lastQue] = append(pipelines[lastQue], pipeline)
|
||||
}
|
||||
}
|
||||
}
|
||||
return pipelines, nil
|
||||
}
|
||||
|
||||
func (s *StatisticClick) countSession(ctx context.Context, quizID int64, from uint64, to uint64, questionIDs []int64) (map[int64]int64, error) {
|
||||
placeholders := make([]string, len(questionIDs))
|
||||
args := make([]interface{}, len(questionIDs)+3)
|
||||
args[0] = quizID
|
||||
for i, id := range questionIDs {
|
||||
placeholders[i] = "?"
|
||||
args[i+1] = id
|
||||
}
|
||||
args[len(args)-2] = from
|
||||
args[len(args)-1] = to
|
||||
|
||||
query := fmt.Sprintf(`
|
||||
SELECT ctxquestionid, COUNT(DISTINCT ctxsession) AS session_count
|
||||
FROM statistics
|
||||
WHERE ctxquizid = ? AND ctxquestionid IN (%s) AND event_time BETWEEN ? AND ?
|
||||
GROUP BY ctxquestionid;
|
||||
`, strings.Join(placeholders, ","))
|
||||
|
||||
rows, err := s.conn.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
counts := make(map[int64]int64)
|
||||
|
||||
for rows.Next() {
|
||||
var questionID int64
|
||||
var count int64
|
||||
err := rows.Scan(&questionID, &count)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
counts[questionID] = count
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return counts, nil
|
||||
}
|
@ -30,6 +30,10 @@ packages:
|
||||
- "./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"
|
||||
engine: "postgresql"
|
||||
|
20
utils/binary_search.go
Normal file
20
utils/binary_search.go
Normal file
@ -0,0 +1,20 @@
|
||||
package utils
|
||||
|
||||
func BinarySearch(target int64, array []int64) bool {
|
||||
left := 0
|
||||
right := len(array) - 1
|
||||
|
||||
for left <= right {
|
||||
mid := (left + right) / 2
|
||||
|
||||
if array[mid] == target {
|
||||
return true
|
||||
} else if array[mid] < target {
|
||||
left = mid + 1
|
||||
} else if array[mid] > target {
|
||||
right = mid - 1
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
Loading…
Reference in New Issue
Block a user