Merge branch 'answerUTM' into 'main'

Answer utm

See merge request backend/quiz/common!19
This commit is contained in:
Mikhail 2024-05-24 12:51:32 +00:00
commit 8d5d3e6973
13 changed files with 311 additions and 477 deletions

@ -305,8 +305,9 @@ INSERT INTO answer(
os, os,
browser, browser,
ip, ip,
start start,
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13); utm
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14);
-- name: GetResultAnswers :many -- name: GetResultAnswers :many
SELECT DISTINCT on (question_id) id, content, quiz_id, question_id, fingerprint, session,created_at, result, new,deleted, device_type,device,os,browser,ip FROM answer WHERE session = ( SELECT DISTINCT on (question_id) id, content, quiz_id, question_id, fingerprint, session,created_at, result, new,deleted, device_type,device,os,browser,ip FROM answer WHERE session = (
@ -914,73 +915,18 @@ WHERE NOT EXISTS (
-- name: GetTokenById :one -- name: GetTokenById :one
SELECT * FROM tokens WHERE accountID = $1; SELECT * FROM tokens WHERE accountID = $1;
-- name: DeletingUTM :exec
UPDATE utms SET Deleted = true WHERE ID = ANY($1::int[]);
-- name: GetUTMsWithPagination :many
SELECT ut.*, COUNT(*) OVER() as total_count
FROM utms ut JOIN (SELECT AmoID FROM users WHERE users.AccountID = $1) u ON ut.AccountID = u.AmoID
WHERE ut.Deleted = false and ut.QuizID = $4
ORDER BY ut.ID OFFSET ($2 - 1) * $3 LIMIT $3;
-- name: SaveUTMs :many
WITH user_data AS (
SELECT AmoID
FROM users
WHERE users.AccountID = $1
), new_UTMs AS (
SELECT (utm->>'AmoFieldID')::INT AS amoFieldID,
COALESCE(utm->>'QuizID', '')::INT AS quizID,
COALESCE(utm->>'Name', '')::varchar(512) AS name,
CURRENT_TIMESTAMP AS createdAt
FROM json_array_elements($2::json) AS utm
), inserted_utms AS(
INSERT INTO utms (AmoFieldID, QuizID, AccountID, Name, createdAt)
SELECT nu.amoFieldID,
nu.quizID,
ud.AmoID,
nu.name,
nu.createdAt
FROM new_UTMs nu
JOIN user_data ud ON true
RETURNING *
)
SELECT * from inserted_utms;
-- name: GetQuizRule :one -- name: GetQuizRule :one
SELECT * FROM rules WHERE QuizID = $1 AND Deleted = false; SELECT * FROM rules WHERE QuizID = $1 AND Deleted = false;
-- name: SetQuizSettings :exec -- name: SetQuizSettings :exec
INSERT INTO rules (AccountID, QuizID, PerformerID, PipelineID, StepID, UTMS, FieldsRule) INSERT INTO rules (AccountID, QuizID, PerformerID, PipelineID, StepID, FieldsRule)
SELECT u.AmoID AS AccountID,$1 AS QuizID,$2 AS PerformerID,$3 AS PipelineID, SELECT u.AmoID AS AccountID,$1 AS QuizID,$2 AS PerformerID,$3 AS PipelineID,
$4 AS StepID,$5 AS UTMS,$6 AS FieldsRule FROM users u WHERE u.AccountID = $7; $4 AS StepID,$5 AS FieldsRule FROM users u WHERE u.AccountID = $6;
-- name: ChangeQuizSettings :exec -- name: ChangeQuizSettings :exec
UPDATE rules UPDATE rules
SET PerformerID = $1,PipelineID = $2,StepID = $3,UTMS = $4,FieldsRule = $5 SET PerformerID = $1,PipelineID = $2,StepID = $3,FieldsRule = $4
WHERE AccountID = (SELECT AmoID FROM users WHERE users.AccountID = $6) AND QuizID = $7 AND Deleted = false; WHERE AccountID = (SELECT AmoID FROM users WHERE users.AccountID = $5) AND QuizID = $6 AND Deleted = false;
-- name: GetUtmsByID :many
SELECT ID,AmoFieldID,QuizID,AccountID,Name
FROM utms
WHERE
ID = ANY($1::int[]) AND Deleted = FALSE;
-- name: GetUserFieldsByID :many
SELECT ID,AmoID,Code,AccountID,Name,Entity,Type
FROM fields
WHERE AccountID = $1 AND Deleted = false;
-- name: UpdateUtms :exec
UPDATE utms AS u
SET name = (update_data ->> 'Name')::varchar(512),
AmoFieldID = (update_data ->> 'AmoFieldID')::INT
FROM json_array_elements($1::json) AS update_data
WHERE u.ID = (update_data ->> 'ID')::INT;
-- name: UpdateUtmsFields :exec
UPDATE utms AS u SET AmoFieldID = f.AmoID FROM fields AS f
WHERE u.Name = f.Name AND u.ID = ANY($1::int[]) AND u.Deleted = FALSE;
-- name: GetQuestionListByIDs :many -- name: GetQuestionListByIDs :many
SELECT * FROM question WHERE id = ANY($1::int[]) AND deleted = FALSE; SELECT * FROM question WHERE id = ANY($1::int[]) AND deleted = FALSE;
@ -1031,7 +977,12 @@ WHERE NOT EXISTS (
); );
-- name: GettingAmoUsersTrueResults :many -- name: GettingAmoUsersTrueResults :many
SELECT a.quiz_id,a.id,a.result,a.question_id,a.content,a.session,t.accesstoken,r.accountid,r.utms,r.fieldsrule,r.performerid,r.stepid,r.pipelineid,(SELECT u.name FROM users u WHERE u.amoid = r.performerid) AS performer_name 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.performerid,r.stepid,r.pipelineid,(SELECT u.name FROM users u WHERE u.amoid = r.performerid) AS performer_name
FROM answer a FROM answer a
INNER JOIN quiz q ON a.quiz_id = q.id INNER JOIN quiz q ON a.quiz_id = q.id
LEFT JOIN amoCRMStatuses s ON a.id = s.AnswerID LEFT JOIN amoCRMStatuses s ON a.id = s.AnswerID
@ -1092,3 +1043,8 @@ WHERE AmoUserID = $1 AND Deleted = false;
-- name: GetFieldByAmoID :one -- name: GetFieldByAmoID :one
SELECT * FROM fields WHERE AmoID = $1 AND Deleted = false; SELECT * FROM fields WHERE AmoID = $1 AND Deleted = false;
-- name: GetUserFieldsByID :many
SELECT ID,AmoID,Code,AccountID,Name,Entity,Type
FROM fields
WHERE AccountID = $1 AND Deleted = false;

50
dal/db_query/utm.sql Normal file

@ -0,0 +1,50 @@
-- name: GetUtmsByID :many
-- SELECT ID,AmoFieldID,QuizID,AccountID,Name
-- FROM utms
-- WHERE
-- ID = ANY($1::int[]) AND Deleted = FALSE;
--
-- name: UpdateUtms :exec
-- UPDATE utms AS u
-- SET name = (update_data ->> 'Name')::varchar(512),
-- AmoFieldID = (update_data ->> 'AmoFieldID')::INT
-- FROM json_array_elements($1::json) AS update_data
-- WHERE u.ID = (update_data ->> 'ID')::INT;
-- name: UpdateUtmsFields :exec
-- UPDATE utms AS u SET AmoFieldID = f.AmoID FROM fields AS f
-- WHERE u.Name = f.Name AND u.ID = ANY($1::int[]) AND u.Deleted = FALSE;
-- name: DeletingUTM :exec
-- UPDATE utms SET Deleted = true WHERE ID = ANY($1::int[]);
-- name: GetUTMsWithPagination :many
-- SELECT ut.*, COUNT(*) OVER() as total_count
-- FROM utms ut JOIN (SELECT AmoID FROM users WHERE users.AccountID = $1) u ON ut.AccountID = u.AmoID
-- WHERE ut.Deleted = false and ut.QuizID = $4
-- ORDER BY ut.ID OFFSET ($2 - 1) * $3 LIMIT $3;
-- name: SaveUTMs :many
-- WITH user_data AS (
-- SELECT AmoID
-- FROM users
-- WHERE users.AccountID = $1
-- ), new_UTMs AS (
-- SELECT (utm->>'AmoFieldID')::INT AS amoFieldID,
-- COALESCE(utm->>'QuizID', '')::INT AS quizID,
-- COALESCE(utm->>'Name', '')::varchar(512) AS name,
-- CURRENT_TIMESTAMP AS createdAt
-- FROM json_array_elements($2::json) AS utm
-- ), inserted_utms AS(
-- INSERT INTO utms (AmoFieldID, QuizID, AccountID, Name, createdAt)
-- SELECT nu.amoFieldID,
-- nu.quizID,
-- ud.AmoID,
-- nu.name,
-- nu.createdAt
-- FROM new_UTMs nu
-- JOIN user_data ud ON true
-- RETURNING *
-- )
-- SELECT * from inserted_utms;

@ -0,0 +1,15 @@
ALTER TABLE answer
DROP COLUMN utm;
CREATE TABLE IF NOT EXISTS utms (
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
AmoFieldID INT NOT NULL DEFAULT 0, -- id field в амо
QuizID INT NOT NULL, -- id опроса
AccountID INT NOT NULL, -- id аккаунта в амо AMOID
Name VARCHAR(512) NOT NULL DEFAULT '', -- название utm
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE rules
ADD COLUMN UTMS INTEGER[];

@ -0,0 +1,5 @@
ALTER TABLE answer
ADD COLUMN utm jsonb NOT NULL DEFAULT '{}';
DROP TABLE IF EXISTS utms;
ALTER TABLE rules
DROP COLUMN IF EXISTS UTMS;

@ -30,23 +30,24 @@ type Amocrmstatus struct {
} }
type Answer struct { type Answer struct {
ID int64 `db:"id" json:"id"` ID int64 `db:"id" json:"id"`
Content sql.NullString `db:"content" json:"content"` Content sql.NullString `db:"content" json:"content"`
QuizID int64 `db:"quiz_id" json:"quiz_id"` QuizID int64 `db:"quiz_id" json:"quiz_id"`
QuestionID int64 `db:"question_id" json:"question_id"` QuestionID int64 `db:"question_id" json:"question_id"`
Fingerprint sql.NullString `db:"fingerprint" json:"fingerprint"` Fingerprint sql.NullString `db:"fingerprint" json:"fingerprint"`
Session sql.NullString `db:"session" json:"session"` Session sql.NullString `db:"session" json:"session"`
CreatedAt sql.NullTime `db:"created_at" json:"created_at"` CreatedAt sql.NullTime `db:"created_at" json:"created_at"`
Result sql.NullBool `db:"result" json:"result"` Result sql.NullBool `db:"result" json:"result"`
New sql.NullBool `db:"new" json:"new"` New sql.NullBool `db:"new" json:"new"`
Deleted sql.NullBool `db:"deleted" json:"deleted"` Deleted sql.NullBool `db:"deleted" json:"deleted"`
Email string `db:"email" json:"email"` Email string `db:"email" json:"email"`
DeviceType string `db:"device_type" json:"device_type"` DeviceType string `db:"device_type" json:"device_type"`
Device string `db:"device" json:"device"` Device string `db:"device" json:"device"`
Os string `db:"os" json:"os"` Os string `db:"os" json:"os"`
Browser string `db:"browser" json:"browser"` Browser string `db:"browser" json:"browser"`
Ip string `db:"ip" json:"ip"` Ip string `db:"ip" json:"ip"`
Start bool `db:"start" json:"start"` Start bool `db:"start" json:"start"`
Utm json.RawMessage `db:"utm" json:"utm"`
} }
type Field struct { type Field struct {
@ -135,7 +136,6 @@ type Rule struct {
Performerid int32 `db:"performerid" json:"performerid"` Performerid int32 `db:"performerid" json:"performerid"`
Pipelineid int32 `db:"pipelineid" json:"pipelineid"` Pipelineid int32 `db:"pipelineid" json:"pipelineid"`
Stepid int32 `db:"stepid" json:"stepid"` Stepid int32 `db:"stepid" json:"stepid"`
Utms []int32 `db:"utms" json:"utms"`
Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"` Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"`
Deleted bool `db:"deleted" json:"deleted"` Deleted bool `db:"deleted" json:"deleted"`
Createdat sql.NullTime `db:"createdat" json:"createdat"` Createdat sql.NullTime `db:"createdat" json:"createdat"`
@ -186,13 +186,3 @@ type User struct {
Amouserid int32 `db:"amouserid" json:"amouserid"` Amouserid int32 `db:"amouserid" json:"amouserid"`
Country string `db:"country" json:"country"` Country string `db:"country" json:"country"`
} }
type Utm struct {
ID int64 `db:"id" json:"id"`
Amofieldid int32 `db:"amofieldid" json:"amofieldid"`
Quizid int32 `db:"quizid" json:"quizid"`
Accountid int32 `db:"accountid" json:"accountid"`
Name string `db:"name" json:"name"`
Deleted bool `db:"deleted" json:"deleted"`
Createdat sql.NullTime `db:"createdat" json:"createdat"`
}

@ -116,15 +116,14 @@ func (q *Queries) ArchiveQuiz(ctx context.Context, arg ArchiveQuizParams) error
const changeQuizSettings = `-- name: ChangeQuizSettings :exec const changeQuizSettings = `-- name: ChangeQuizSettings :exec
UPDATE rules UPDATE rules
SET PerformerID = $1,PipelineID = $2,StepID = $3,UTMS = $4,FieldsRule = $5 SET PerformerID = $1,PipelineID = $2,StepID = $3,FieldsRule = $4
WHERE AccountID = (SELECT AmoID FROM users WHERE users.AccountID = $6) AND QuizID = $7 AND Deleted = false WHERE AccountID = (SELECT AmoID FROM users WHERE users.AccountID = $5) AND QuizID = $6 AND Deleted = false
` `
type ChangeQuizSettingsParams struct { type ChangeQuizSettingsParams struct {
Performerid int32 `db:"performerid" json:"performerid"` Performerid int32 `db:"performerid" json:"performerid"`
Pipelineid int32 `db:"pipelineid" json:"pipelineid"` Pipelineid int32 `db:"pipelineid" json:"pipelineid"`
Stepid int32 `db:"stepid" json:"stepid"` Stepid int32 `db:"stepid" json:"stepid"`
Utms []int32 `db:"utms" json:"utms"`
Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"` Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"`
Accountid string `db:"accountid" json:"accountid"` Accountid string `db:"accountid" json:"accountid"`
Quizid int32 `db:"quizid" json:"quizid"` Quizid int32 `db:"quizid" json:"quizid"`
@ -135,7 +134,6 @@ func (q *Queries) ChangeQuizSettings(ctx context.Context, arg ChangeQuizSettings
arg.Performerid, arg.Performerid,
arg.Pipelineid, arg.Pipelineid,
arg.Stepid, arg.Stepid,
pq.Array(arg.Utms),
arg.Fieldsrule, arg.Fieldsrule,
arg.Accountid, arg.Accountid,
arg.Quizid, arg.Quizid,
@ -974,15 +972,6 @@ func (q *Queries) DeleteUsers(ctx context.Context, dollar_1 []int64) error {
return err return err
} }
const deletingUTM = `-- name: DeletingUTM :exec
UPDATE utms SET Deleted = true WHERE ID = ANY($1::int[])
`
func (q *Queries) DeletingUTM(ctx context.Context, dollar_1 []int32) error {
_, err := q.db.ExecContext(ctx, deletingUTM, pq.Array(dollar_1))
return err
}
const deviceStatistics = `-- name: DeviceStatistics :many const deviceStatistics = `-- name: DeviceStatistics :many
WITH DeviceStats AS ( WITH DeviceStats AS (
SELECT SELECT
@ -2204,7 +2193,7 @@ func (q *Queries) GetQuizHistory(ctx context.Context, arg GetQuizHistoryParams)
} }
const getQuizRule = `-- name: GetQuizRule :one const getQuizRule = `-- name: GetQuizRule :one
SELECT id, accountid, quizid, performerid, pipelineid, stepid, utms, fieldsrule, deleted, createdat FROM rules WHERE QuizID = $1 AND Deleted = false SELECT id, accountid, quizid, performerid, pipelineid, stepid, fieldsrule, deleted, createdat FROM rules WHERE QuizID = $1 AND Deleted = false
` `
func (q *Queries) GetQuizRule(ctx context.Context, quizid int32) (Rule, error) { func (q *Queries) GetQuizRule(ctx context.Context, quizid int32) (Rule, error) {
@ -2217,7 +2206,6 @@ func (q *Queries) GetQuizRule(ctx context.Context, quizid int32) (Rule, error) {
&i.Performerid, &i.Performerid,
&i.Pipelineid, &i.Pipelineid,
&i.Stepid, &i.Stepid,
pq.Array(&i.Utms),
&i.Fieldsrule, &i.Fieldsrule,
&i.Deleted, &i.Deleted,
&i.Createdat, &i.Createdat,
@ -2427,68 +2415,6 @@ func (q *Queries) GetTokenById(ctx context.Context, accountid string) (Token, er
return i, err return i, err
} }
const getUTMsWithPagination = `-- name: GetUTMsWithPagination :many
SELECT ut.id, ut.amofieldid, ut.quizid, ut.accountid, ut.name, ut.deleted, ut.createdat, COUNT(*) OVER() as total_count
FROM utms ut JOIN (SELECT AmoID FROM users WHERE users.AccountID = $1) u ON ut.AccountID = u.AmoID
WHERE ut.Deleted = false and ut.QuizID = $4
ORDER BY ut.ID OFFSET ($2 - 1) * $3 LIMIT $3
`
type GetUTMsWithPaginationParams struct {
Accountid string `db:"accountid" json:"accountid"`
Column2 interface{} `db:"column_2" json:"column_2"`
Limit int32 `db:"limit" json:"limit"`
Quizid int32 `db:"quizid" json:"quizid"`
}
type GetUTMsWithPaginationRow struct {
ID int64 `db:"id" json:"id"`
Amofieldid int32 `db:"amofieldid" json:"amofieldid"`
Quizid int32 `db:"quizid" json:"quizid"`
Accountid int32 `db:"accountid" json:"accountid"`
Name string `db:"name" json:"name"`
Deleted bool `db:"deleted" json:"deleted"`
Createdat sql.NullTime `db:"createdat" json:"createdat"`
TotalCount int64 `db:"total_count" json:"total_count"`
}
func (q *Queries) GetUTMsWithPagination(ctx context.Context, arg GetUTMsWithPaginationParams) ([]GetUTMsWithPaginationRow, error) {
rows, err := q.db.QueryContext(ctx, getUTMsWithPagination,
arg.Accountid,
arg.Column2,
arg.Limit,
arg.Quizid,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetUTMsWithPaginationRow
for rows.Next() {
var i GetUTMsWithPaginationRow
if err := rows.Scan(
&i.ID,
&i.Amofieldid,
&i.Quizid,
&i.Accountid,
&i.Name,
&i.Deleted,
&i.Createdat,
&i.TotalCount,
); 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 getUserFieldsByID = `-- name: GetUserFieldsByID :many const getUserFieldsByID = `-- name: GetUserFieldsByID :many
SELECT ID,AmoID,Code,AccountID,Name,Entity,Type SELECT ID,AmoID,Code,AccountID,Name,Entity,Type
FROM fields FROM fields
@ -2792,52 +2718,13 @@ func (q *Queries) GetUsersWithPagination(ctx context.Context, arg GetUsersWithPa
return items, nil return items, nil
} }
const getUtmsByID = `-- name: GetUtmsByID :many
SELECT ID,AmoFieldID,QuizID,AccountID,Name
FROM utms
WHERE
ID = ANY($1::int[]) AND Deleted = FALSE
`
type GetUtmsByIDRow struct {
ID int64 `db:"id" json:"id"`
Amofieldid int32 `db:"amofieldid" json:"amofieldid"`
Quizid int32 `db:"quizid" json:"quizid"`
Accountid int32 `db:"accountid" json:"accountid"`
Name string `db:"name" json:"name"`
}
func (q *Queries) GetUtmsByID(ctx context.Context, dollar_1 []int32) ([]GetUtmsByIDRow, error) {
rows, err := q.db.QueryContext(ctx, getUtmsByID, pq.Array(dollar_1))
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetUtmsByIDRow
for rows.Next() {
var i GetUtmsByIDRow
if err := rows.Scan(
&i.ID,
&i.Amofieldid,
&i.Quizid,
&i.Accountid,
&i.Name,
); 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 gettingAmoUsersTrueResults = `-- name: GettingAmoUsersTrueResults :many const gettingAmoUsersTrueResults = `-- name: GettingAmoUsersTrueResults :many
SELECT a.quiz_id,a.id,a.result,a.question_id,a.content,a.session,t.accesstoken,r.accountid,r.utms,r.fieldsrule,r.performerid,r.stepid,r.pipelineid,(SELECT u.name FROM users u WHERE u.amoid = r.performerid) AS performer_name 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.performerid,r.stepid,r.pipelineid,(SELECT u.name FROM users u WHERE u.amoid = r.performerid) AS performer_name
FROM answer a FROM answer a
INNER JOIN quiz q ON a.quiz_id = q.id INNER JOIN quiz q ON a.quiz_id = q.id
LEFT JOIN amoCRMStatuses s ON a.id = s.AnswerID LEFT JOIN amoCRMStatuses s ON a.id = s.AnswerID
@ -2858,9 +2745,9 @@ type GettingAmoUsersTrueResultsRow struct {
QuestionID int64 `db:"question_id" json:"question_id"` QuestionID int64 `db:"question_id" json:"question_id"`
Content sql.NullString `db:"content" json:"content"` Content sql.NullString `db:"content" json:"content"`
Session sql.NullString `db:"session" json:"session"` Session sql.NullString `db:"session" json:"session"`
Utm json.RawMessage `db:"utm" json:"utm"`
Accesstoken string `db:"accesstoken" json:"accesstoken"` Accesstoken string `db:"accesstoken" json:"accesstoken"`
Accountid int32 `db:"accountid" json:"accountid"` Accountid int32 `db:"accountid" json:"accountid"`
Utms []int32 `db:"utms" json:"utms"`
Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"` Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"`
Performerid int32 `db:"performerid" json:"performerid"` Performerid int32 `db:"performerid" json:"performerid"`
Stepid int32 `db:"stepid" json:"stepid"` Stepid int32 `db:"stepid" json:"stepid"`
@ -2884,9 +2771,9 @@ func (q *Queries) GettingAmoUsersTrueResults(ctx context.Context) ([]GettingAmoU
&i.QuestionID, &i.QuestionID,
&i.Content, &i.Content,
&i.Session, &i.Session,
&i.Utm,
&i.Accesstoken, &i.Accesstoken,
&i.Accountid, &i.Accountid,
pq.Array(&i.Utms),
&i.Fieldsrule, &i.Fieldsrule,
&i.Performerid, &i.Performerid,
&i.Stepid, &i.Stepid,
@ -2920,24 +2807,26 @@ INSERT INTO answer(
os, os,
browser, browser,
ip, ip,
start start,
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13) utm
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14)
` `
type InsertAnswersParams struct { type InsertAnswersParams struct {
Content sql.NullString `db:"content" json:"content"` Content sql.NullString `db:"content" json:"content"`
QuizID int64 `db:"quiz_id" json:"quiz_id"` QuizID int64 `db:"quiz_id" json:"quiz_id"`
QuestionID int64 `db:"question_id" json:"question_id"` QuestionID int64 `db:"question_id" json:"question_id"`
Fingerprint sql.NullString `db:"fingerprint" json:"fingerprint"` Fingerprint sql.NullString `db:"fingerprint" json:"fingerprint"`
Session sql.NullString `db:"session" json:"session"` Session sql.NullString `db:"session" json:"session"`
Result sql.NullBool `db:"result" json:"result"` Result sql.NullBool `db:"result" json:"result"`
Email string `db:"email" json:"email"` Email string `db:"email" json:"email"`
DeviceType string `db:"device_type" json:"device_type"` DeviceType string `db:"device_type" json:"device_type"`
Device string `db:"device" json:"device"` Device string `db:"device" json:"device"`
Os string `db:"os" json:"os"` Os string `db:"os" json:"os"`
Browser string `db:"browser" json:"browser"` Browser string `db:"browser" json:"browser"`
Ip string `db:"ip" json:"ip"` Ip string `db:"ip" json:"ip"`
Start bool `db:"start" json:"start"` Start bool `db:"start" json:"start"`
Utm json.RawMessage `db:"utm" json:"utm"`
} }
func (q *Queries) InsertAnswers(ctx context.Context, arg InsertAnswersParams) error { func (q *Queries) InsertAnswers(ctx context.Context, arg InsertAnswersParams) error {
@ -2955,6 +2844,7 @@ func (q *Queries) InsertAnswers(ctx context.Context, arg InsertAnswersParams) er
arg.Browser, arg.Browser,
arg.Ip, arg.Ip,
arg.Start, arg.Start,
arg.Utm,
) )
return err return err
} }
@ -3357,81 +3247,10 @@ func (q *Queries) QuizCopyQid(ctx context.Context, arg QuizCopyQidParams) (QuizC
return i, err return i, err
} }
const saveUTMs = `-- name: SaveUTMs :many
WITH user_data AS (
SELECT AmoID
FROM users
WHERE users.AccountID = $1
), new_UTMs AS (
SELECT (utm->>'AmoFieldID')::INT AS amoFieldID,
COALESCE(utm->>'QuizID', '')::INT AS quizID,
COALESCE(utm->>'Name', '')::varchar(512) AS name,
CURRENT_TIMESTAMP AS createdAt
FROM json_array_elements($2::json) AS utm
), inserted_utms AS(
INSERT INTO utms (AmoFieldID, QuizID, AccountID, Name, createdAt)
SELECT nu.amoFieldID,
nu.quizID,
ud.AmoID,
nu.name,
nu.createdAt
FROM new_UTMs nu
JOIN user_data ud ON true
RETURNING id, amofieldid, quizid, accountid, name, deleted, createdat
)
SELECT id, amofieldid, quizid, accountid, name, deleted, createdat from inserted_utms
`
type SaveUTMsParams struct {
Accountid string `db:"accountid" json:"accountid"`
Column2 json.RawMessage `db:"column_2" json:"column_2"`
}
type SaveUTMsRow struct {
ID int64 `db:"id" json:"id"`
Amofieldid int32 `db:"amofieldid" json:"amofieldid"`
Quizid int32 `db:"quizid" json:"quizid"`
Accountid int32 `db:"accountid" json:"accountid"`
Name string `db:"name" json:"name"`
Deleted bool `db:"deleted" json:"deleted"`
Createdat sql.NullTime `db:"createdat" json:"createdat"`
}
func (q *Queries) SaveUTMs(ctx context.Context, arg SaveUTMsParams) ([]SaveUTMsRow, error) {
rows, err := q.db.QueryContext(ctx, saveUTMs, arg.Accountid, arg.Column2)
if err != nil {
return nil, err
}
defer rows.Close()
var items []SaveUTMsRow
for rows.Next() {
var i SaveUTMsRow
if err := rows.Scan(
&i.ID,
&i.Amofieldid,
&i.Quizid,
&i.Accountid,
&i.Name,
&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 setQuizSettings = `-- name: SetQuizSettings :exec const setQuizSettings = `-- name: SetQuizSettings :exec
INSERT INTO rules (AccountID, QuizID, PerformerID, PipelineID, StepID, UTMS, FieldsRule) INSERT INTO rules (AccountID, QuizID, PerformerID, PipelineID, StepID, FieldsRule)
SELECT u.AmoID AS AccountID,$1 AS QuizID,$2 AS PerformerID,$3 AS PipelineID, SELECT u.AmoID AS AccountID,$1 AS QuizID,$2 AS PerformerID,$3 AS PipelineID,
$4 AS StepID,$5 AS UTMS,$6 AS FieldsRule FROM users u WHERE u.AccountID = $7 $4 AS StepID,$5 AS FieldsRule FROM users u WHERE u.AccountID = $6
` `
type SetQuizSettingsParams struct { type SetQuizSettingsParams struct {
@ -3439,7 +3258,6 @@ type SetQuizSettingsParams struct {
Performerid int32 `db:"performerid" json:"performerid"` Performerid int32 `db:"performerid" json:"performerid"`
Pipelineid int32 `db:"pipelineid" json:"pipelineid"` Pipelineid int32 `db:"pipelineid" json:"pipelineid"`
Stepid int32 `db:"stepid" json:"stepid"` Stepid int32 `db:"stepid" json:"stepid"`
Utms []int32 `db:"utms" json:"utms"`
Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"` Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"`
Accountid string `db:"accountid" json:"accountid"` Accountid string `db:"accountid" json:"accountid"`
} }
@ -3450,7 +3268,6 @@ func (q *Queries) SetQuizSettings(ctx context.Context, arg SetQuizSettingsParams
arg.Performerid, arg.Performerid,
arg.Pipelineid, arg.Pipelineid,
arg.Stepid, arg.Stepid,
pq.Array(arg.Utms),
arg.Fieldsrule, arg.Fieldsrule,
arg.Accountid, arg.Accountid,
) )
@ -3661,29 +3478,6 @@ func (q *Queries) UpdateUsers(ctx context.Context, dollar_1 json.RawMessage) err
return err return err
} }
const updateUtms = `-- name: UpdateUtms :exec
UPDATE utms AS u
SET name = (update_data ->> 'Name')::varchar(512),
AmoFieldID = (update_data ->> 'AmoFieldID')::INT
FROM json_array_elements($1::json) AS update_data
WHERE u.ID = (update_data ->> 'ID')::INT
`
func (q *Queries) UpdateUtms(ctx context.Context, dollar_1 json.RawMessage) error {
_, err := q.db.ExecContext(ctx, updateUtms, dollar_1)
return err
}
const updateUtmsFields = `-- name: UpdateUtmsFields :exec
UPDATE utms AS u SET AmoFieldID = f.AmoID FROM fields AS f
WHERE u.Name = f.Name AND u.ID = ANY($1::int[]) AND u.Deleted = FALSE
`
func (q *Queries) UpdateUtmsFields(ctx context.Context, dollar_1 []int32) error {
_, err := q.db.ExecContext(ctx, updateUtmsFields, pq.Array(dollar_1))
return err
}
const updatingDealAmoStatus = `-- name: UpdatingDealAmoStatus :exec const updatingDealAmoStatus = `-- name: UpdatingDealAmoStatus :exec
UPDATE amoCRMStatuses SET Status = $1 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) 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)

@ -141,7 +141,7 @@ type Rule struct {
/* - айдишник этапа*/ /* - айдишник этапа*/
Stepid int32 `json:"StepID"` Stepid int32 `json:"StepID"`
/* - список UTM для этого опроса*/ /* - список UTM для этого опроса*/
Utms []int32 `json:"UTMs"` //Utms []int32 `json:"UTMs"`
/* - правила заполнения полей сущностей в амо*/ /* - правила заполнения полей сущностей в амо*/
Fieldsrule Fieldsrule `json:"FieldsRule"` Fieldsrule Fieldsrule `json:"FieldsRule"`
/* - флаг мягкого удаления*/ /* - флаг мягкого удаления*/
@ -197,22 +197,22 @@ const (
TypeContactAddress ContactQuizConfig = "address" TypeContactAddress ContactQuizConfig = "address"
) )
type UTM struct { //type UTM struct {
/* - айдишник в нашей системе Primary Key*/ // /* - айдишник в нашей системе Primary Key*/
ID int64 `json:"ID"` // ID int64 `json:"ID"`
/* - айдишник кастомного поля в амо*/ // /* - айдишник кастомного поля в амо*/
Amofieldid int32 `json:"AmoFieldID"` // Amofieldid int32 `json:"AmoFieldID"`
/* - айдишник квиза*/ // /* - айдишник квиза*/
Quizid int32 `json:"QuizID"` // Quizid int32 `json:"QuizID"`
/* - связь с аккаунтом в интеграции амо id амо*/ // /* - связь с аккаунтом в интеграции амо id амо*/
Accountid int32 `json:"AccountID"` // Accountid int32 `json:"AccountID"`
/* - название тега в амо*/ // /* - название тега в амо*/
Name string `json:"Name"` // Name string `json:"Name"`
/* - флаг мягкого удаления*/ // /* - флаг мягкого удаления*/
Deleted bool `json:"Deleted"` // Deleted bool `json:"Deleted"`
/* - таймштамп создания тега в нашей системе*/ // /* - таймштамп создания тега в нашей системе*/
Createdat int64 `json:"CreatedAt"` // Createdat int64 `json:"CreatedAt"`
} //}
type FieldType string type FieldType string
@ -268,7 +268,7 @@ type AmoUsersTrueResults struct {
Session string Session string
AccessToken string AccessToken string
AmoAccountID int32 AmoAccountID int32
UTMs []int32 UTMs UTMSavingMap
FieldsRule Fieldsrule FieldsRule Fieldsrule
PerformerID int32 PerformerID int32
StepID int32 StepID int32

@ -13,14 +13,14 @@ type PaginationReq struct {
} }
type RulesReq struct { type RulesReq struct {
PerformerID int32 // айдишник ответственного за сделку PerformerID int32 // айдишник ответственного за сделку
PipelineID int32 // айдишник воронки PipelineID int32 // айдишник воронки
StepID int32 // айдишник этапа StepID int32 // айдишник этапа
Utms []int32 // список UTM для этого опроса //Utms []int32 // список UTM для этого опроса
Fieldsrule Fieldsrule // правила заполнения полей сущностей в амо Fieldsrule Fieldsrule // правила заполнения полей сущностей в амо
} }
type SaveUserListUTMReq struct { //type SaveUserListUTMReq struct {
/* - список utm для сохранения. сохранять только те, которых в этом аккаунте ещё нет*/ // /* - список utm для сохранения. сохранять только те, которых в этом аккаунте ещё нет*/
Utms []UTM `json:"utms"` // Utms []UTM `json:"utms"`
} //}

@ -24,12 +24,12 @@ type GetCurrentAccountResp struct {
Createdat int64 `json:"CreatedAt"` Createdat int64 `json:"CreatedAt"`
} }
type GetListUserUTMResp struct { //type GetListUserUTMResp struct {
/* - общее количество юзеров, которые у нас закешированы для этого пользователя*/ // /* - общее количество юзеров, которые у нас закешированы для этого пользователя*/
Count int64 `json:"count"` // Count int64 `json:"count"`
/* - список юзеров, которые были закешированы нашим сервисом*/ // /* - список юзеров, которые были закешированы нашим сервисом*/
Items []UTM `json:"items"` // Items []UTM `json:"items"`
} //}
type ListSavedIDUTMResp struct { type ListSavedIDUTMResp struct {
/* - список айдишников сохранённых меток*/ /* - список айдишников сохранённых меток*/

@ -130,6 +130,7 @@ type Answer struct {
IP string IP string
OS string OS string
Start bool Start bool
Utm UTMSavingMap
} }
type ResultContent struct { type ResultContent struct {
@ -292,3 +293,5 @@ type AnswerExport struct {
New bool `json:"new"` New bool `json:"new"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
} }
type UTMSavingMap map[string]string

@ -811,10 +811,10 @@ func (r *AmoRepository) ChangeQuizSettings(ctx context.Context, request *model.R
Performerid: request.PerformerID, Performerid: request.PerformerID,
Pipelineid: request.PipelineID, Pipelineid: request.PipelineID,
Stepid: request.StepID, Stepid: request.StepID,
Utms: request.Utms, //Utms: request.Utms,
Fieldsrule: jsonFieldRule, Fieldsrule: jsonFieldRule,
Accountid: accountID, Accountid: accountID,
Quizid: int32(quizID), Quizid: int32(quizID),
}) })
if err != nil { if err != nil {
@ -833,10 +833,10 @@ func (r *AmoRepository) SetQuizSettings(ctx context.Context, request *model.Rule
Performerid: request.PerformerID, Performerid: request.PerformerID,
Pipelineid: request.PipelineID, Pipelineid: request.PipelineID,
Stepid: request.StepID, Stepid: request.StepID,
Utms: request.Utms, //Utms: request.Utms,
Fieldsrule: jsonFieldRule, Fieldsrule: jsonFieldRule,
Accountid: accountID, Accountid: accountID,
Quizid: int32(quizID), Quizid: int32(quizID),
}) })
if err != nil { if err != nil {
@ -865,8 +865,8 @@ func (r *AmoRepository) GettingQuizRules(ctx context.Context, quizID int) (*mode
Performerid: row.Performerid, Performerid: row.Performerid,
Pipelineid: row.Pipelineid, Pipelineid: row.Pipelineid,
Stepid: row.Stepid, Stepid: row.Stepid,
Utms: row.Utms, //Utms: row.Utms,
Fieldsrule: fieldsRule, Fieldsrule: fieldsRule,
}, nil }, nil
} }
@ -891,115 +891,117 @@ func (r *AmoRepository) UpdateFieldRules(ctx context.Context, fieldRules model.F
// методы UTMs // методы UTMs
func (r *AmoRepository) DeletingUserUtm(ctx context.Context, request *model.ListDeleteUTMIDsReq) error { func (r *AmoRepository) DeletingUserUtm(ctx context.Context, request *model.ListDeleteUTMIDsReq) error {
err := r.queries.DeletingUTM(ctx, request.Utms) //err := r.queries.DeletingUTM(ctx, request.Utms)
if err != nil { //if err != nil {
return err // return err
} //}
return nil return nil
} }
// todo нужно ли тут ограничивать индексом что то // todo нужно ли тут ограничивать индексом что то
func (r *AmoRepository) SavingUserUtm(ctx context.Context, utms []model.UTM, accountID string) (*model.ListSavedIDUTMResp, error) { //func (r *AmoRepository) SavingUserUtm(ctx context.Context, utms []model.UTM, accountID string) (*model.ListSavedIDUTMResp, error) {
column2, err := json.Marshal(utms) // column2, err := json.Marshal(utms)
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
rows, err := r.queries.SaveUTMs(ctx, sqlcgen.SaveUTMsParams{ // rows, err := r.queries.SaveUTMs(ctx, sqlcgen.SaveUTMsParams{
Accountid: accountID, // Accountid: accountID,
Column2: column2, // Column2: column2,
}) // })
//
var ids []int64 // var ids []int64
//
for _, row := range rows { // for _, row := range rows {
ids = append(ids, row.ID) // ids = append(ids, row.ID)
} // }
//
return &model.ListSavedIDUTMResp{ // return &model.ListSavedIDUTMResp{
Ids: ids, // Ids: ids,
}, nil // }, nil
} //
// return nil, nil
func (r *AmoRepository) GettingUserUtm(ctx context.Context, request *model.PaginationReq, accountID string, quizID int) (*model.GetListUserUTMResp, error) { //}
rows, err := r.queries.GetUTMsWithPagination(ctx, sqlcgen.GetUTMsWithPaginationParams{ //
Accountid: accountID, //func (r *AmoRepository) GettingUserUtm(ctx context.Context, request *model.PaginationReq, accountID string, quizID int) (*model.GetListUserUTMResp, error) {
Column2: request.Page, // rows, err := r.queries.GetUTMsWithPagination(ctx, sqlcgen.GetUTMsWithPaginationParams{
Limit: request.Size, // Accountid: accountID,
Quizid: int32(quizID), // Column2: request.Page,
}) // Limit: request.Size,
// Quizid: int32(quizID),
if err != nil { // })
return nil, err //
} // if err != nil {
// return nil, err
var count int64 // }
var utmS []model.UTM //
// var count int64
for _, row := range rows { // var utmS []model.UTM
count = row.TotalCount //
utm := model.UTM{ // for _, row := range rows {
ID: row.ID, // count = row.TotalCount
Amofieldid: row.Amofieldid, // utm := model.UTM{
Quizid: row.Quizid, // ID: row.ID,
Accountid: row.Accountid, // Amofieldid: row.Amofieldid,
Name: row.Name, // Quizid: row.Quizid,
Deleted: row.Deleted, // Accountid: row.Accountid,
Createdat: row.Createdat.Time.Unix(), // Name: row.Name,
} // Deleted: row.Deleted,
// Createdat: row.Createdat.Time.Unix(),
utmS = append(utmS, utm) // }
} //
// utmS = append(utmS, utm)
return &model.GetListUserUTMResp{ // }
Count: count, //
Items: utmS, // return &model.GetListUserUTMResp{
}, nil // Count: count,
} // Items: utmS,
// }, nil
func (r *AmoRepository) GetUtmsByID(ctx context.Context, ids []int32) ([]model.UTM, error) { //}
rows, err := r.queries.GetUtmsByID(ctx, ids) //
if err != nil { //func (r *AmoRepository) GetUtmsByID(ctx context.Context, ids []int32) ([]model.UTM, error) {
return nil, err // rows, err := r.queries.GetUtmsByID(ctx, ids)
} // if err != nil {
// return nil, err
var utmS []model.UTM // }
for _, row := range rows { //
utm := model.UTM{ // var utmS []model.UTM
ID: row.ID, // for _, row := range rows {
Amofieldid: row.Amofieldid, // utm := model.UTM{
Quizid: row.Quizid, // ID: row.ID,
Accountid: row.Accountid, // Amofieldid: row.Amofieldid,
Name: row.Name, // Quizid: row.Quizid,
} // Accountid: row.Accountid,
// Name: row.Name,
utmS = append(utmS, utm) // }
} //
// utmS = append(utmS, utm)
return utmS, nil // }
} //
// return utmS, nil
func (r *AmoRepository) UpdateUTMs(ctx context.Context, utms []model.UTM) error { //}
dollar1, err := json.Marshal(utms) //
if err != nil { //func (r *AmoRepository) UpdateUTMs(ctx context.Context, utms []model.UTM) error {
return err // dollar1, err := json.Marshal(utms)
} // if err != nil {
err = r.queries.UpdateUtms(ctx, dollar1) // return err
// }
if err != nil { // err = r.queries.UpdateUtms(ctx, dollar1)
return err //
} // if err != nil {
// return err
return nil // }
} //
// return nil
func (r *AmoRepository) UpdateUtmsFields(ctx context.Context, ids []int32) error { //}
err := r.queries.UpdateUtmsFields(ctx, ids) //
if err != nil { //func (r *AmoRepository) UpdateUtmsFields(ctx context.Context, ids []int32) error {
return err // err := r.queries.UpdateUtmsFields(ctx, ids)
} // if err != nil {
// return err
return nil // }
} //
// return nil
//}
func (r *AmoRepository) GettingAmoUsersTrueResults(ctx context.Context) ([]model.AmoUsersTrueResults, error) { func (r *AmoRepository) GettingAmoUsersTrueResults(ctx context.Context) ([]model.AmoUsersTrueResults, error) {
rows, err := r.queries.GettingAmoUsersTrueResults(ctx) rows, err := r.queries.GettingAmoUsersTrueResults(ctx)
@ -1015,6 +1017,13 @@ func (r *AmoRepository) GettingAmoUsersTrueResults(ctx context.Context) ([]model
if err != nil { if err != nil {
return nil, err return nil, err
} }
var utm model.UTMSavingMap
err = json.Unmarshal(row.Utm, &utm)
if err != nil {
return nil, err
}
result := model.AmoUsersTrueResults{ result := model.AmoUsersTrueResults{
QuizID: row.QuizID, QuizID: row.QuizID,
AnswerID: row.ID, AnswerID: row.ID,
@ -1024,7 +1033,7 @@ func (r *AmoRepository) GettingAmoUsersTrueResults(ctx context.Context) ([]model
Session: row.Session.String, Session: row.Session.String,
AccessToken: row.Accesstoken, AccessToken: row.Accesstoken,
AmoAccountID: row.Accountid, AmoAccountID: row.Accountid,
UTMs: row.Utms, UTMs: utm,
FieldsRule: fieldsRule, FieldsRule: fieldsRule,
PerformerID: row.Performerid, PerformerID: row.Performerid,
StepID: row.Stepid, StepID: row.Stepid,

@ -3,6 +3,7 @@ package answer
import ( import (
"context" "context"
"database/sql" "database/sql"
"encoding/json"
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/dal/sqlcgen" "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/model"
) )
@ -40,6 +41,14 @@ func (r *AnswerRepository) CreateAnswers(ctx context.Context, answers []model.An
} }
for _, ans := range answers { for _, ans := range answers {
var utmJSON []byte
if ans.Utm != nil {
utmJSON, err = json.Marshal(ans.Utm)
if err != nil {
return nil, []error{err}
}
}
params := sqlcgen.InsertAnswersParams{ params := sqlcgen.InsertAnswersParams{
Content: sql.NullString{String: ans.Content, Valid: true}, Content: sql.NullString{String: ans.Content, Valid: true},
QuizID: int64(quizID), QuizID: int64(quizID),
@ -54,9 +63,10 @@ func (r *AnswerRepository) CreateAnswers(ctx context.Context, answers []model.An
Browser: ans.Browser, Browser: ans.Browser,
Os: ans.OS, Os: ans.OS,
Start: ans.Start, Start: ans.Start,
Utm: utmJSON,
} }
err := r.queries.InsertAnswers(ctx, params) err = r.queries.InsertAnswers(ctx, params)
if err != nil { if err != nil {
errs = append(errs, err) errs = append(errs, err)
} else { } else {

@ -24,6 +24,8 @@ packages:
- "./dal/schema/000009_init.down.sql" - "./dal/schema/000009_init.down.sql"
- "./dal/schema/000010_init.up.sql" - "./dal/schema/000010_init.up.sql"
- "./dal/schema/000010_init.down.sql" - "./dal/schema/000010_init.down.sql"
- "./dal/schema/000011_init.up.sql"
- "./dal/schema/000011_init.down.sql"
engine: "postgresql" engine: "postgresql"
emit_json_tags: true emit_json_tags: true
emit_db_tags: true emit_db_tags: true