all bitrix repo methods and queries

This commit is contained in:
skeris 2025-05-13 16:40:18 +03:00
parent f6665ff212
commit 063bbb55e2
11 changed files with 3148 additions and 2 deletions

@ -2,3 +2,4 @@
- ветка vlangTG - создание миграций для добавления таблицы интеграции и с ботом для телеги и таблицы текущего статуса прохождения опроса через телегабот. и всякие энамы вокруг этого - ветка vlangTG - создание миграций для добавления таблицы интеграции и с ботом для телеги и таблицы текущего статуса прохождения опроса через телегабот. и всякие энамы вокруг этого
- ветка chMigrate: миграция сложных запросов на LTV для промокода и мини партнёрки для перехода по quizLogo из сложных походов по внутренней сети на получение данных из clickhouse - ветка chMigrate: миграция сложных запросов на LTV для промокода и мини партнёрки для перехода по quizLogo из сложных походов по внутренней сети на получение данных из clickhouse
- ветка bitrix: - все необходимые методы dal и запросы необходимые для работы интеграции с битриксом

@ -14,6 +14,7 @@ import (
"gitea.pena/SQuiz/common/repository/amo" "gitea.pena/SQuiz/common/repository/amo"
"gitea.pena/SQuiz/common/repository/answer" "gitea.pena/SQuiz/common/repository/answer"
"gitea.pena/SQuiz/common/repository/question" "gitea.pena/SQuiz/common/repository/question"
"gitea.pena/SQuiz/common/repository/bitrix"
"gitea.pena/SQuiz/common/repository/quiz" "gitea.pena/SQuiz/common/repository/quiz"
"gitea.pena/SQuiz/common/repository/result" "gitea.pena/SQuiz/common/repository/result"
"gitea.pena/SQuiz/common/repository/statistics" "gitea.pena/SQuiz/common/repository/statistics"
@ -199,6 +200,75 @@ func (d *AmoDal) Close(ctx context.Context) error {
return nil return nil
} }
type BitrixDal struct {
conn *sql.DB
queries *sqlcgen.Queries
BitrixRepo *bitrix.BitrixRepository
QuizRepo *quiz.QuizRepository
QuestionRepo *question.QuestionRepository
AccountRepo *account.AccountRepository
AnswerRepo *answer.AnswerRepository
}
func NewBitrixDal(ctx context.Context, cred string) (*BitrixDal, error) {
pool, err := sql.Open("postgres", cred)
if err != nil {
return nil, err
}
timeoutCtx, cancel := context.WithTimeout(ctx, time.Second)
defer cancel()
if err := pool.PingContext(timeoutCtx); err != nil {
return nil, err
}
queries := sqlcgen.New(pool)
bitrixRepo := bitrix.NewBitrixRepository(bitrix.Deps{
Queries: queries,
Pool: pool,
})
quizRepo := quiz.NewQuizRepository(quiz.Deps{
Queries: queries,
Pool: pool,
})
questionRepo := question.NewQuestionRepository(question.Deps{
Queries: queries,
Pool: pool,
})
accountRepo := account.NewAccountRepository(account.Deps{
Queries: queries,
Pool: pool,
})
answerRepo := answer.NewAnswerRepository(answer.Deps{
Queries: queries,
Pool: pool,
})
return &BitrixDal{
conn: pool,
queries: queries,
BitrixRepo: bitrixRepo,
QuizRepo: quizRepo,
QuestionRepo: questionRepo,
AccountRepo: accountRepo,
AnswerRepo: answerRepo,
}, nil
}
func (d *BitrixDal) Close(ctx context.Context) error {
err := d.conn.Close()
if err != nil {
return err
}
return nil
}
type ClickHouseDAL struct { type ClickHouseDAL struct {
conn *sql.DB conn *sql.DB
StatisticClickRepo *statistics.StatisticClick StatisticClickRepo *statistics.StatisticClick

@ -1094,3 +1094,311 @@ SELECT accountid FROM quiz WHERE id = $1 AND accountid = $2;
-- name: CheckLeadTargetOwner :one -- name: CheckLeadTargetOwner :one
SELECT accountid FROM leadtarget WHERE id = $1 AND accountid = $2; SELECT accountid FROM leadtarget WHERE id = $1 AND accountid = $2;
-- BITRIX
-- name: GetUsersBitrixWithPagination :many
WITH user_data AS (
SELECT BitrixID FROM BitrixAccounts WHERE BitrixAccounts.AccountID = $1 AND BitrixAccounts.Deleted = false
)
SELECT u.*, COUNT(*) OVER() as total_count
FROM BitrixAccountUsers u
JOIN user_data a ON u.BitrixID = a.BitrixID
WHERE u.Deleted = false
ORDER BY u.ID OFFSET ($2 - 1) * $3 LIMIT $3;
-- name: SoftDeleteBitrixAccount :exec
WITH bitrixCompany AS (
SELECT BitrixID FROM BitrixAccounts WHERE BitrixAccounts.AccountID = $1 AND deleted = false
),usersDel AS (
UPDATE BitrixAccountUsers SET Deleted = true WHERE BitrixID = (SELECT BitrixID FROM bitrixCompany)
),
companyDel AS ( UPDATE BitrixAccounts SET Deleted = true WHERE BitrixID = (SELECT BitrixID FROM bitrixCompany)
)
DELETE FROM BitrixTokens WHERE BitrixTokens.AccountID = $1;
-- name: GetCurrentBitrixCompany :one
SELECT * FROM BitrixAccounts WHERE AccountID = $1 AND Deleted = false;
-- name: CheckExpiredBitrixToken :one
SELECT * FROM BitrixTokens WHERE AccountID = $1 AND Expiration <= NOW();
-- name: CreateBitrixAccount :exec
INSERT INTO BitrixAccounts (AccountID, BitrixID, Subdomain)
VALUES ($1, $2, $3);
-- name: AddBitrixAccountUser :exec
INSERT INTO BitrixAccountUsers (AccountID, BitrixIDUserID, Name, LastName, SecondName, Title,Email,UFDepartment,WorkPosition)
VALUES ($1, $2, $3, $4, $5, $6,$7,$8,$9);
-- name: UpdateBitrixAccountUser :exec
UPDATE BitrixAccountUsers SET Name = $3, LastName = $4, SecondName = $5, Title= $6, Email = $7,UFDepartment = $8,WorkPosition=$9
WHERE AccountID = $1 AND BitrixIDUserID = $2 AND deleted = false;
-- name: UpdateBitrixAccount :exec
UPDATE BitrixAccounts SET Subdomain = $2 WHERE AccountID = $1 AND Deleted = false;
-- name: GetBitrixTokenById :one
SELECT * FROM BitrixTokens WHERE accountID = $1;
-- name: DeleteBitrixUsers :exec
UPDATE BitrixAccountUsers SET Deleted = true WHERE ID = ANY($1::bigint[]);
-- name: GetUserUsersByIDBitrix :many
SELECT * FROM BitrixAccountUsers WHERE accountID = $1 AND Deleted = false;
-- name: CreateBitrixWebHook :exec
INSERT INTO BitrixTokens (AccountID, RefreshToken, AccessToken, AuthCode, Expiration, CreatedAt)
VALUES ($1, $2, $3, $4, $5, $6);
-- name: WebhookBitrixUpdate :exec
UPDATE BitrixTokens SET AccessToken = $1,RefreshToken = $2,Expiration = to_timestamp(($3)::bigint) AT TIME ZONE 'UTC' + INTERVAL '3 hours',CreatedAt = to_timestamp(($4)::bigint) AT TIME ZONE 'UTC' + INTERVAL '3 hours'
WHERE accountID = $5;
-- name: GetAllBitrixTokens :many
SELECT * FROM BitrixTokens;
-- name: WebhookBitrixDelete :exec
WITH companyDel AS (
UPDATE BitrixAccounts SET Deleted = true WHERE BitrixAccounts.BitrixID = $1 RETURNING AccountID
),
userDel AS (
UPDATE BitrixAccountUsers SET Deleted = true WHERE AccountID = $1
)
DELETE FROM BitrixTokens WHERE AccountID IN (SELECT AccountID FROM companyDel);
-- name: GetBitrixPipelinesWithPagination :many
WITH user_data AS (
SELECT BitrixID FROM BitrixAccounts WHERE BitrixAccounts.AccountID = $1 AND BitrixAccounts.Deleted = false
)
SELECT p.*, COUNT(*) OVER() as total_count
FROM PipelineBitrix p JOIN user_data u ON p.AccountID = u.BitrixID
WHERE p.Deleted = false
ORDER BY p.ID OFFSET ($2 - 1) * $3 LIMIT $3;
-- name: DeleteBitrixPipelines :exec
UPDATE PipelineBitrix SET Deleted = true WHERE ID = ANY($1::bigint[]);
-- name: GetUserBitrixPipelinesByID :many
SELECT * FROM PipelineBitrix WHERE AccountID = $1 AND Deleted = false;
-- name: CheckBitrixPipelines :many
WITH new_pipelines AS (
SELECT (pipeline->>'bitrixID')::INT AS BitrixID,
(pipeline->>'accountID')::varchar(255) AS AccountID,
COALESCE(pipeline->>'name', '')::varchar(255) AS Name,
(pipeline->>'entityTypeId')::INT as EntityTypeId,
CURRENT_TIMESTAMP AS createdAt
FROM json_array_elements($1::json) AS pipeline
), inserted_pipelines AS(
INSERT INTO PipelineBitrix (BitrixID, AccountID, Name, EntityTypeId, createdAt)
SELECT np.BitrixID,
np.AccountID,
np.Name,
np.EntityTypeId,
np.createdAt
FROM new_pipelines np
ON CONFLICT (BitrixID, AccountID) WHERE Deleted = false DO NOTHING
RETURNING *
)
SELECT np.*
FROM new_pipelines np
WHERE NOT EXISTS (
SELECT *
FROM inserted_pipelines ins
WHERE ins.BitrixID = np.BitrixID AND ins.AccountID = np.AccountID
);
-- name: UpdateBitrixPipelines :exec
UPDATE PipelineBitrix AS p
SET Name = (update_data ->> 'name')::varchar(255),EntityTypeId = (update_data ->> 'entityTypeId')::INT
FROM json_array_elements($1::json) AS update_data
WHERE p.BitrixID = (update_data ->> 'BitrixID')::INT
AND p.AccountID = (update_data ->> 'AccountID')::varchar(255);
-- name: GetBitrixStepsWithPagination :many
WITH user_data AS (
SELECT BitrixID FROM BitrixAccounts WHERE BitrixAccounts.AccountID = $1 AND BitrixAccounts.Deleted = false
)
SELECT s.*, COUNT(*) OVER() as total_count
FROM StepBitrix s JOIN user_data u ON s.AccountID = u.BitrixID
WHERE s.Deleted = false ORDER BY s.ID OFFSET ($2 - 1) * $3 LIMIT $3;
-- name: DeleteBitrixSteps :exec
UPDATE StepBitrix SET Deleted = true WHERE ID = ANY($1::bigint[]);
-- name: GetUserBitrixStepsByID :many
SELECT * FROM StepBitrix WHERE AccountID = $1 AND Deleted = false;
-- name: CheckBitrixSteps :many
WITH new_steps AS (
SELECT (step->>'bitrixID')::VARCHAR(255) AS BitrixID,
(step->>'pipelineID')::INT AS PipelineID,
(step->>'accountID')::VARCHAR(255) AS AccountID,
(step->>'entityID')::VARCHAR(255) AS EntityID,
(step->>'statusID')::VARCHAR(255) AS StatusID,
COALESCE(step->>'name', '')::VARCHAR(255) AS Name,
COALESCE(step->>'nameInit', '')::VARCHAR(255) AS NameInit,
COALESCE(step->>'color', '')::VARCHAR(50) AS Color,
CURRENT_TIMESTAMP AS CreatedAt
FROM json_array_elements($1::json) AS step
), inserted_steps AS (
INSERT INTO StepBitrix (BitrixID, PipelineID, AccountID,EntityID, StatusID, Name,NameInit, Color, CreatedAt)
SELECT ns.BitrixID,
ns.PipelineID,
ns.AccountID,
ns.EntityID,
ns.StatusID,
ns.Name,
ns.NameInit,
ns.Color,
ns.CreatedAt
FROM new_steps ns
ON CONFLICT (BitrixID, AccountID) WHERE Deleted = false DO NOTHING
RETURNING *
)
SELECT ns.*
FROM new_steps ns
WHERE NOT EXISTS (
SELECT *
FROM inserted_steps ins
WHERE ins.BitrixID = ns.BitrixID AND ins.AccountID = ns.AccountID
);
-- name: UpdateBitrixSteps :exec
UPDATE StepBitrix AS s SET
Name = (update_data ->> 'name')::varchar(255),
NameInit = (update_data ->> 'nameInit')::varchar(255),
Color = (update_data ->> 'color')::varchar(50),
EntityID = (update_data ->> 'entityID')::varchar(255),
StatusID = (update_data ->> 'statusID')::varchar(255),
PipelineID = (update_data ->> 'pipelineID')::INT
FROM json_array_elements($1::json) AS update_data
WHERE s.BitrixID = (update_data ->> 'bitrixID')::VARCHAR(255)
AND s.AccountID = (update_data ->> 'accountID')::VARCHAR(255);
-- name: GetBitrixFieldsWithPagination :many
WITH user_data AS (
SELECT BitrixID FROM BitrixAccounts WHERE BitrixAccounts.AccountID = $1 AND BitrixAccounts.Deleted = false
)
SELECT f.*, COUNT(*) OVER() as total_count
FROM BitrixFields f JOIN user_data u ON f.AccountID = u.BitrixID
WHERE f.Deleted = false
ORDER BY f.ID OFFSET ($2 - 1) * $3 LIMIT $3;
-- name: GetUserBitrixFieldsByID :many
SELECT * FROM BitrixFields WHERE AccountID = $1 AND Deleted = false;
-- name: DeleteBitrixFields :exec
UPDATE BitrixFields SET Deleted = true WHERE ID = ANY($1::bigint[]);
-- name: GetBitrixFieldByID :one
SELECT * FROM BitrixFields WHERE BitrixID = $1 AND Deleted = false;
-- name: CheckBitrixFields :many
WITH user_data AS (
SELECT BitrixID FROM BitrixAccounts WHERE BitrixAccounts.AccountID = $1 AND BitrixAccounts.Deleted = false
), new_fields AS (
SELECT
(field->>'bitrixID')::VARCHAR(255) AS BitrixID,
(field->>'accountID')::VARCHAR(255) AS AccountID,
CAST(field->>'entityID' AS FieldsType) AS EntityID,
COALESCE(field->>'fieldName', '')::VARCHAR(255) AS FieldName,
COALESCE(field->>'editFromLabel', '')::VARCHAR(255) AS EditFromLabel,
CAST(field->>'fieldType' AS CustomFieldsType) AS FieldType,
CURRENT_TIMESTAMP AS CreatedAt
FROM json_array_elements($2::json) AS field
), inserted_fields AS (
INSERT INTO BitrixFields (BitrixID, AccountID, EntityID, FieldName, EditFromLabel, FieldType, CreatedAt)
SELECT
nf.BitrixID,
ud.BitrixID AS AccountID,
nf.EntityID,
nf.FieldName,
nf.EditFromLabel,
nf.FieldType,
nf.CreatedAt
FROM new_fields nf
JOIN user_data ud ON true
ON CONFLICT (BitrixID, AccountID, EntityID) DO NOTHING
RETURNING *
)
SELECT nf.*, ud.BitrixID AS AccountID
FROM new_fields nf
JOIN user_data ud ON true
WHERE NOT EXISTS (
SELECT *
FROM inserted_fields ins
JOIN user_data ud ON true
WHERE ins.BitrixID = nf.BitrixID AND ins.AccountID = ud.BitrixID AND ins.EntityID = nf.EntityID
);
-- name: UpdateBitrixFields :exec
UPDATE BitrixFields AS f SET
FieldName = (update_data ->> 'fieldName')::varchar(255),
EditFromLabel = (update_data ->> 'editFromLabel')::varchar(255),
FieldType = (update_data ->> 'fieldType')::CustomFieldsType
FROM json_array_elements($1::json) AS update_data
WHERE f.BitrixID = (update_data ->> 'bitrixID')::VARCHAR(255)
AND f.AccountID = (update_data ->> 'accountID')::VARCHAR(255)
AND f.EntityID = (update_data ->> 'entityID')::FieldsType;
-- name: ChangeBitrixQuizSettings :one
UPDATE BitrixRule
SET PerformerID = $1,PipelineID = $2,TypeID = $3,StageID= $4,SourceID = $5,StatusID = $6,FieldsRule = $7, TagsToAdd=$8, LeadFlag = $9
WHERE AccountID = (SELECT BitrixID FROM bitrixaccounts WHERE bitrixaccounts.AccountID = $10 AND bitrixaccounts.Deleted = false) AND QuizID = $11 AND Deleted = false
RETURNING id;
-- name: SetBitrixQuizSettings :one
INSERT INTO BitrixRule (AccountID, QuizID, PerformerID, PipelineID, TypeID,StageID,SourceID,StatusID, FieldsRule,TagsToAdd,LeadFlag)
SELECT u.bitrixid AS AccountID,$1 AS QuizID,$2 AS PerformerID,$3 AS PipelineID,
$4 AS TypeID,$5 AS StageID,$6 AS SourceID,$7 AS StatusID,$8 AS FieldsRule,$9 AS TagsToAdd, $10 AS LeadFlag FROM bitrixaccounts u WHERE u.AccountID = $11 AND u.Deleted = false
RETURNING id;
-- name: GetBitrixQuizRule :one
SELECT * FROM BitrixRule WHERE QuizID = $1 AND Deleted = false;
-- name: UpdateBitrixFieldRules :exec
UPDATE BitrixRule SET FieldsRule = $1
WHERE AccountID = (SELECT BitrixID FROM bitrixaccounts WHERE bitrixaccounts.AccountID = $2 AND bitrixaccounts.Deleted = false) AND QuizID = $3 AND Deleted = false;
-- name: GettingBitrixUsersTrueResults :many
SELECT a.quiz_id,a.id,a.result,a.question_id,a.content,a.session,
COALESCE((SELECT a2.utm
FROM answer a2
WHERE a2.start = true AND a2.session = a.session
LIMIT 1), '{}'::jsonb) AS utm
,t.accesstoken,r.accountid,r.fieldsrule,r.tagstoadd,r.performerid,r.TypeID,r.StageID,r.SourceID,r.StatusID,r.pipelineid,(SELECT u.name FROM BitrixAccountUsers u WHERE u.bitrixiduserid = r.performerid AND u.deleted = false) AS performer_name,u.subdomain,u.accountid,r.leadflag
FROM answer a
INNER JOIN quiz q ON a.quiz_id = q.id
LEFT JOIN bitrixcrmstatuses s ON a.id = s.AnswerID
INNER JOIN bitrixrule r ON q.id = r.QuizID
INNER JOIN bitrixtokens t ON q.accountid = t.AccountID
INNER JOIN bitrixaccounts u ON q.accountid = u.accountid AND u.bitrixid = r.accountid
WHERE a.result = true
AND s.id IS NULL
AND a.deleted = false
AND r.deleted = false
AND q.deleted = false
AND u.deleted = false;
-- name: SettingDealBitrixStatus :exec
INSERT INTO bitrixCRMStatuses (AccountID, DealID, AnswerID, Status)
SELECT u.BitrixID, $1, $2, $3
FROM BitrixTokens AS t
JOIN BitrixAccounts AS u ON t.AccountID = u.AccountID
WHERE t.AccessToken = $4 AND u.Deleted = false;
-- name: GetExistingContactBitrix :many
WITH getBitrixID AS (
SELECT BitrixID FROM bitrixContact WHERE bitrixContact.AccountID = $1 AND bitrixContact.Field = ANY($2::text[])
) SELECT * FROM bitrixContact
WHERE bitrixContact.AccountID = $1 AND bitrixContact.BitrixID IN (SELECT BitrixID FROM getBitrixID);
-- name: InsertContactBitrix :one
INSERT INTO bitrixContact (AccountID, BitrixID, Field) VALUES ($1, $2, $3) RETURNING BitrixID;
-- name: UpdateBitrixContact :exec
UPDATE bitrixContact SET Field = $1,BitrixID=$3 WHERE ID = $2;

@ -1 +1,35 @@
DROP TABLE IF EXISTS BitrixTokens;
DROP TABLE IF EXISTS StepBitrix;
DROP TABLE IF EXISTS PipelineBitrix;
DROP TABLE IF EXISTS BitrixAccounts;
DROP TABLE IF EXISTS BitrixAccountUsers;
DROP TABLE IF EXISTS BitrixFields;
DROP TABLE IF EXISTS BitrixRule;
DROP TABLE IF EXISTS bitrixCRMStatuses;
DROP TABLE IF EXISTS bitrixContact;
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'CustomFieldsType') THEN
DROP TYPE CustomFieldsType;
END IF;
END $$;
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'FieldsType') THEN
DROP TYPE FieldsType;
END IF;
END $$;
DROP INDEX IF EXISTS idx_unique_pipeline_bitrix;
DROP INDEX IF EXISTS idx_unique_step_bitrix;
DROP INDEX IF EXISTS idx_unique_field_bitrix;
ALTER TABLE answer DROP COLUMN IF EXISTS version; ALTER TABLE answer DROP COLUMN IF EXISTS version;

@ -1 +1,149 @@
CREATE TABLE IF NOT EXISTS BitrixTokens (
AccountID VARCHAR(30) PRIMARY KEY, -- связь с users AccountID неявная посредством join
RefreshToken TEXT NOT NULL ,
AccessToken TEXT NOT NULL ,
AuthCode TEXT NOT NULL , -- код авторизации который получаем при вебхук
Expiration TIMESTAMP NOT NULL, -- время истечения токенов
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'FieldsType') THEN
CREATE TYPE FieldsType AS ENUM (
'CRM_LEAD',
'CRM_COMPANY',
'CRM_CONTACT',
'CRM_DEAL',
'CRM_INVOICE',
'CRM_SMART_INVOICE',
'CRM_QUOTE',
'CRM_REQUISITE'
);
END IF;
END $$;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'CustomFieldsType') THEN
CREATE TYPE CustomFieldsType AS ENUM (
'string',
'integer',
'double',
'boolean',
'datetime',
'enumeration',
'iblock_section',
'iblock_element',
'employee',
'crm_status',
'crm',
'address',
'money',
'url',
'file',
'crm_pena_tag'
);
END IF;
END $$;
CREATE TABLE IF NOT EXISTS BitrixFields (
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
BitrixID VARCHAR(255) NOT NULL, -- Айдишник field в битриксе
AccountID VARCHAR(255) NOT NULL,-- ID портала битрикса
EntityID FieldsType NOT NULL,-- тип поля
FieldName VARCHAR(255) NOT NULL,-- имя поля
EditFromLabel VARCHAR(255) NOT NULL,-- заголовок вопроса
FieldType CustomFieldsType NOT NULL, -- тип поля
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS BitrixAccountUsers (
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
AccountID VARCHAR(255) NOT NULL, -- ID портала битрикса
BitrixIDUserID VARCHAR(255) NOT NULL, -- ID пользователя в битриксе
Name VARCHAR(255) NOT NULL default '', -- Имя
LastName VARCHAR(255) NOT NULL default '',-- Фамилия
SecondName VARCHAR(255) NOT NULL default '', -- Отчество
Title VARCHAR(255) NOT NULL default '',
Email VARCHAR(255) NOT NULL default '', -- Почта
UFDepartment INT[], -- Массив департаментов
WorkPosition VARCHAR(255) NOT NULL default '', -- Должность
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS BitrixAccounts (
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
AccountID VARCHAR(30) NOT NULL, -- ID аккаунта у нас
BitrixID VARCHAR(255) NOT NULL, -- ID портала битрикса
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
Subdomain VARCHAR(50) NOT NULL -- поддомен
);
CREATE TABLE IF NOT EXISTS PipelineBitrix (
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
BitrixID INT NOT NULL, -- Айдишник воронки в битриксе
AccountID VARCHAR(255) NOT NULL, -- ID портала битрикса
Name VARCHAR(255) NOT NULL, -- Название воронки
EntityTypeId INT NOT NULL, -- Тип по номерам
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT validEntityType CHECK (EntityTypeId IN (1, 2, 3, 4, 5, 7, 8, 31))
);
CREATE TABLE IF NOT EXISTS StepBitrix (
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
AccountID VARCHAR(255) NOT NULL, -- ID портала битрикса
BitrixID VARCHAR(255) NOT NULL, -- Айдишник состояния в битриксе
EntityID VARCHAR(255) NOT NULL, -- Тип сущности
StatusID VARCHAR(255) NOT NULL, -- Текстовый формат ID статуса
Name VARCHAR(255) NOT NULL default '', -- Название
NameInit VARCHAR(255) NOT NULL default '', -- возможно это изначальное название
Color VARCHAR(50) NOT NULL default '', -- Цвет
PipelineID INT NOT NULL, -- ID воронки
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS BitrixRule (
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
AccountID VARCHAR(255) NOT NULL, -- ID портала битрикса
QuizID INT NOT NULL, -- ID квиза на которое вешается правило
PerformerID VARCHAR(255) NOT NULL, -- ID пользователя в битриксе который ответсвенный
PipelineID INT NOT NULL, -- ID воронки
TypeID VARCHAR(255) NOT NULL, -- шаг сделки только с "ENTITY_ID":"DEAL_TYPE","STATUS_ID":"SALE"
StageID VARCHAR(255) NOT NULL, -- стадия сделки, шаг "ENTITY_ID":"DEAL_STAGE","STATUS_ID":"NEW"
SourceID VARCHAR(255) NOT NULL, -- тип источника, шаг "ENTITY_ID":"SOURCE","STATUS_ID":"CALL"
StatusID VARCHAR(255) NOT NULL, -- тип источника, шаг "ENTITY_ID":"STATUS","STATUS_ID":"IN_PROCESS"
FieldsRule JSONB NOT NULL DEFAULT '{}', -- вложенная структура
TagsToAdd JSONB NOT NULL DEFAULT '{}', -- структура тегов которые надо дбавлять
Deleted BOOLEAN NOT NULL DEFAULT FALSE,
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
LeadFlag BOOLEAN NOT NULL DEFAULT FALSE -- если true то делаем лид а не сделку
);
CREATE TABLE IF NOT EXISTS bitrixCRMStatuses (
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
AccountID VARCHAR(255) NOT NULL, -- ID портала битрикса
DealID INT NOT NULL, -- id сделки или лида в которую добавлялось
AnswerID BIGINT NOT NULL REFERENCES answer(id), -- id true result который вызвал действие
Status TEXT NOT NULL DEFAULT '', -- запись о ошибке, либо успехе
CreatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS bitrixContact (
ID BIGSERIAL UNIQUE NOT NULL PRIMARY KEY,
AccountID VARCHAR(255) NOT NULL, -- ID "компании" в амо
BitrixID INT NOT NULL, -- ID контакта в амо
Field text NOT NULL DEFAULT '' -- значение чего то email? phone? etc
);
CREATE UNIQUE INDEX idx_unique_pipeline_bitrix ON PipelineBitrix (BitrixID, AccountID) WHERE Deleted = false;
CREATE UNIQUE INDEX idx_unique_step_bitrix ON StepBitrix (BitrixID, AccountID) WHERE Deleted = false;
CREATE UNIQUE INDEX idx_unique_field_bitrix ON BitrixFields (BitrixID, AccountID, EntityID);
ALTER TABLE answer ADD COLUMN version integer NOT NULL default 0; ALTER TABLE answer ADD COLUMN version integer NOT NULL default 0;

@ -69,6 +69,84 @@ type Answer struct {
Version int32 `db:"version" json:"version"` Version int32 `db:"version" json:"version"`
} }
type Bitrixaccount struct {
ID int64 `db:"id" json:"id"`
Accountid string `db:"accountid" json:"accountid"`
Bitrixid string `db:"bitrixid" json:"bitrixid"`
Deleted bool `db:"deleted" json:"deleted"`
Createdat time.Time `db:"createdat" json:"createdat"`
Subdomain string `db:"subdomain" json:"subdomain"`
}
type Bitrixaccountuser struct {
ID int64 `db:"id" json:"id"`
Accountid string `db:"accountid" json:"accountid"`
Bitrixiduserid string `db:"bitrixiduserid" json:"bitrixiduserid"`
Name string `db:"name" json:"name"`
Lastname string `db:"lastname" json:"lastname"`
Secondname string `db:"secondname" json:"secondname"`
Title string `db:"title" json:"title"`
Email string `db:"email" json:"email"`
Ufdepartment []int32 `db:"ufdepartment" json:"ufdepartment"`
Workposition string `db:"workposition" json:"workposition"`
Deleted bool `db:"deleted" json:"deleted"`
Createdat time.Time `db:"createdat" json:"createdat"`
}
type Bitrixcontact struct {
ID int64 `db:"id" json:"id"`
Accountid string `db:"accountid" json:"accountid"`
Bitrixid int32 `db:"bitrixid" json:"bitrixid"`
Field string `db:"field" json:"field"`
}
type Bitrixcrmstatus struct {
ID int64 `db:"id" json:"id"`
Accountid string `db:"accountid" json:"accountid"`
Dealid int32 `db:"dealid" json:"dealid"`
Answerid int64 `db:"answerid" json:"answerid"`
Status string `db:"status" json:"status"`
Createdat time.Time `db:"createdat" json:"createdat"`
}
type Bitrixfield struct {
ID int64 `db:"id" json:"id"`
Bitrixid string `db:"bitrixid" json:"bitrixid"`
Accountid string `db:"accountid" json:"accountid"`
Entityid interface{} `db:"entityid" json:"entityid"`
Fieldname string `db:"fieldname" json:"fieldname"`
Editfromlabel string `db:"editfromlabel" json:"editfromlabel"`
Fieldtype interface{} `db:"fieldtype" json:"fieldtype"`
Deleted bool `db:"deleted" json:"deleted"`
Createdat time.Time `db:"createdat" json:"createdat"`
}
type Bitrixrule struct {
ID int64 `db:"id" json:"id"`
Accountid string `db:"accountid" json:"accountid"`
Quizid int32 `db:"quizid" json:"quizid"`
Performerid string `db:"performerid" json:"performerid"`
Pipelineid int32 `db:"pipelineid" json:"pipelineid"`
Typeid string `db:"typeid" json:"typeid"`
Stageid string `db:"stageid" json:"stageid"`
Sourceid string `db:"sourceid" json:"sourceid"`
Statusid string `db:"statusid" json:"statusid"`
Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"`
Tagstoadd json.RawMessage `db:"tagstoadd" json:"tagstoadd"`
Deleted bool `db:"deleted" json:"deleted"`
Createdat time.Time `db:"createdat" json:"createdat"`
Leadflag bool `db:"leadflag" json:"leadflag"`
}
type Bitrixtoken struct {
Accountid string `db:"accountid" json:"accountid"`
Refreshtoken string `db:"refreshtoken" json:"refreshtoken"`
Accesstoken string `db:"accesstoken" json:"accesstoken"`
Authcode string `db:"authcode" json:"authcode"`
Expiration time.Time `db:"expiration" json:"expiration"`
Createdat time.Time `db:"createdat" json:"createdat"`
}
type Field struct { type Field struct {
ID int64 `db:"id" json:"id"` ID int64 `db:"id" json:"id"`
Amoid int32 `db:"amoid" json:"amoid"` Amoid int32 `db:"amoid" json:"amoid"`
@ -102,6 +180,16 @@ type Pipeline struct {
Createdat sql.NullTime `db:"createdat" json:"createdat"` Createdat sql.NullTime `db:"createdat" json:"createdat"`
} }
type Pipelinebitrix struct {
ID int64 `db:"id" json:"id"`
Bitrixid int32 `db:"bitrixid" json:"bitrixid"`
Accountid string `db:"accountid" json:"accountid"`
Name string `db:"name" json:"name"`
Entitytypeid int32 `db:"entitytypeid" json:"entitytypeid"`
Deleted bool `db:"deleted" json:"deleted"`
Createdat time.Time `db:"createdat" json:"createdat"`
}
type Privilege struct { type Privilege struct {
ID int32 `db:"id" json:"id"` ID int32 `db:"id" json:"id"`
Privilegeid string `db:"privilegeid" json:"privilegeid"` Privilegeid string `db:"privilegeid" json:"privilegeid"`
@ -183,6 +271,20 @@ type Step struct {
Createdat sql.NullTime `db:"createdat" json:"createdat"` Createdat sql.NullTime `db:"createdat" json:"createdat"`
} }
type Stepbitrix struct {
ID int64 `db:"id" json:"id"`
Accountid string `db:"accountid" json:"accountid"`
Bitrixid string `db:"bitrixid" json:"bitrixid"`
Entityid string `db:"entityid" json:"entityid"`
Statusid string `db:"statusid" json:"statusid"`
Name string `db:"name" json:"name"`
Nameinit string `db:"nameinit" json:"nameinit"`
Color string `db:"color" json:"color"`
Pipelineid int32 `db:"pipelineid" json:"pipelineid"`
Deleted bool `db:"deleted" json:"deleted"`
Createdat time.Time `db:"createdat" json:"createdat"`
}
type Tag struct { type Tag struct {
ID int64 `db:"id" json:"id"` ID int64 `db:"id" json:"id"`
Amoid int32 `db:"amoid" json:"amoid"` Amoid int32 `db:"amoid" json:"amoid"`

File diff suppressed because it is too large Load Diff

176
model/bitrix.go Normal file

@ -0,0 +1,176 @@
package model
import "time"
type BitrixAccountUser struct {
ID int64 `json:"id"` // ID пользователя
AccountID string `json:"accountID"` // ID портала битрикса, id account company
BitrixIDUserID string `json:"bitrixUserID"` // ID пользователя в битриксе
Name string `json:"name"` // Имя
LastName string `json:"lastName"` // фамилия
SecondName string `json:"secondName"` // отчество
Title string `json:"title"`
Email string `json:"email"` // почта
UFDepartment []int32 `json:"uf_department"`
WorkPosition string `json:"workPosition"` // должность
Deleted bool `json:"deleted"` /* - флаг мягкого удаления*/
CreatedAt time.Time `json:"createdAt"` /* - таймштамп создания воронки в нашей системе*/
}
type BitrixAccount struct {
ID int64 `json:"id"` // ID компании
AccountID string `json:"accountID"` // ID аккаунта нас
BitrixID string `json:"bitrixID"` // ID портала битрикса
Deleted bool `json:"deleted"`
CreatedAt time.Time `json:"createdAt"`
Subdomain string `json:"subdomain"` // поддомен
Stale bool `json:"stale"`
}
type PipelineBitrix struct {
ID int64 `json:"ID"` // айдишник в нашей системе Primary Key
BitrixID int32 `json:"bitrixID"` /* - айдишник воронки*/
AccountID string `json:"accountID"` // ID портала битрикса, id account company
Name string `json:"name"` // название
EntityTypeId IntegerEntityType `json:"entityTypeId"` // тип по номерам
Deleted bool `json:"deleted"` /* - флаг мягкого удаления*/
Createdat int64 `json:"createdAt"` /* - таймштамп создания воронки в нашей системе*/
}
type StepBitrix struct {
ID int64 `json:"ID"` /* - айдишник в нашей системе Primary Key*/
AccountID string `json:"accountID"` // ID портала битрикса, id account company
BitrixID string `json:"bitrixID"` /* - айдишник состояния в битриксе*/
EntityID string `json:"entityID"` // тип сущности
StatusID string `json:"statusID"` // текстовый формат id статуса
Name string `json:"name"` // название
NameInit string `json:"nameInit"`
Color string `json:"color"` // цвет
PipelineID int32 `json:"pipelineID"` // id воронки
Deleted bool `json:"deleted"` /* - флаг мягкого удаления*/
Createdat int64 `json:"createdAt"` /* - таймштамп создания воронки в нашей системе*/
}
//type Tag struct {
// /* - айдишник в нашей системе Primary Key*/
// ID int64 `json:"ID"`
// /* - айдишник тега в амо*/
// Amoid int32 `json:"AmoID"`
// /* - связь с аккаунтом в интеграции амо id аккаунта в амо*/
// Accountid int32 `json:"AccountID"`
// /* - сущность, к которой принадлежит этот тег. Наверное, стоит сделать через enum в базе*/
// Entity EntityType `json:"Entity"`
// /* - название тега в амо*/
// Name string `json:"Name"`
// /* - цвет тега в амо*/
// Color *string `json:"Color"`
// /* - флаг мягкого удаления*/
// Deleted bool `json:"Deleted"`
// /* - таймштамп создания тега в нашей системе*/
// Createdat int64 `json:"CreatedAt"`
//}
type BitrixField struct {
ID int64 `json:"ID"` /* - айдишник в нашей системе Primary Key*/
AccountID string `json:"accountID"` // ID портала битрикса, id account company
BitrixID string `json:"bitrixID"` // id field in bitrix int or string)))
EntityID FieldsType `json:"entityID"` // тип поля
FieldName string `json:"fieldName"` // имя поля, которое втсраивается в request
EditFromLabel string `json:"editFromLabel"` // заголовк вопроса тут
FieldType CustomFieldsType `json:"fieldType"` // тип поля
Deleted bool `json:"deleted"` /* - флаг мягкого удаления*/
Createdat int64 `json:"createdAt"` /* - таймштамп создания воронки в нашей системе*/
}
type BitrixRulesReq struct {
PerformerID string `json:"PerformerID"` // айдишник ответственного за сделку
PipelineID int32 `json:"PipelineID"` // айдишник воронки
TypeID string `json:"TypeID"` // шаг сделки только с "ENTITY_ID":"DEAL_TYPE","STATUS_ID":"SALE"
StageID string `json:"StageID"` // стадия сделки, шаг "ENTITY_ID":"DEAL_STAGE","STATUS_ID":"NEW"
SourceID string `json:"SourceID"` // тип источника, шаг "ENTITY_ID":"SOURCE","STATUS_ID":"CALL"
FieldsRule BitrixFieldRules `json:"FieldsRule"` // правила заполнения полей сущностей в амо
TagsToAdd TagsToAdd `json:"TagsToAdd"` // теги добавляемые к сделке todo kostil'
LeadFlag bool `json:"LeadFlag"` // флаг показывающий на то что нужен лид а не дил
StatusID string `json:"StatusID"` // Идентификатор стадии лида
}
type BitrixFieldRules struct {
Lead BitrixFieldRule `json:"lead"`
Deal BitrixFieldRule `json:"deal"`
Company BitrixFieldRule `json:"company"`
Contact BitrixContactRules `json:"contact"`
}
type BitrixContactRules struct {
// ключ имя, значение id кастомного поля
ContactRuleMap map[string]string
QuestionID map[int]string `json:"QuestionID"` // ключ id вопроса значение id астомного поля
}
type BitrixFieldRule struct {
QuestionID map[int]string `json:"QuestionID"`
}
type BitrixRule struct {
ID int64 `json:"ID"` // айдишник в нашей системе
AccountID string `json:"accountID"` // ID портала битрикса, id account company
QuizID int32 `json:"QuizID"` // айдишник опроса
PerformerID string `json:"PerformerID"` // айдишник ответственного за сделку
PipelineID int32 `json:"PipelineID"` // айдишник воронки
TypeID string `json:"TypeID"` // шаг сделки только с "ENTITY_ID":"DEAL_TYPE","STATUS_ID":"SALE"
StageID string `json:"StageID"` // стадия сделки, шаг "ENTITY_ID":"DEAL_STAGE","STATUS_ID":"NEW"
SourceID string `json:"SourceID"` // тип источника, шаг "ENTITY_ID":"SOURCE","STATUS_ID":"CALL"
FieldsRule BitrixFieldRules `json:"FieldsRule"` // правила заполнения полей сущностей в амо
TagsToAdd TagsToAdd `json:"TagsToAdd"` // теги добавляемые к сделке todo kostil'
Deleted bool `json:"Deleted"` // флаг мягкого удаления
CreatedAt int64 `json:"CreatedAt"` // таймштамп создания
LeadFlag bool `json:"LeadFlag"` // флаг показывающий на то что нужен лид а не дил
StatusID string `json:"StatusID"` // Идентификатор стадии лида
}
type BitrixUsersTrueResults struct {
QuizID int64
AnswerID int64
Result bool
QuestionID int64
Content string
Session string
AccessToken string
AmoAccountID string
UTMs UTMSavingMap
FieldsRule BitrixFieldRules
TagsToAdd TagsToAdd
PerformerID string
TypeID string // шаг сделки только с "ENTITY_ID":"DEAL_TYPE","STATUS_ID":"SALE"
StageID string // стадия сделки, шаг "ENTITY_ID":"DEAL_STAGE","STATUS_ID":"NEW"
SourceID string // тип источника, шаг "ENTITY_ID":"SOURCE","STATUS_ID":"CALL"
PipelineID int32
PerformerName string
SubDomain string
QuizAccountID string
LeadFlag bool
StatusID string // Идентификатор стадии лида
}
//var TypeMapping = map[string]FieldType{
// "variant": TypeAmoText, //TypeAmoChainedList,
// "images": TypeAmoText, //TypeAmoFile,
// "varimg": TypeAmoText, //TypeAmoFile,
// "file": TypeAmoFile,
// "text": TypeAmoText,
// "emoji": TypeAmoText,
// "select": TypeAmoText, //TypeAmoSelect,
// "date": TypeAmoText, //TypeAmoDate,
// "number": TypeAmoText, //TypeAmoNumeric,
// "page": TypeAmoText,
// "rating": TypeAmoText,
// "result": TypeAmoText,
//}
type ContactBitrix struct {
ID int64
AccountID string // id аккаунта в амо к которому привязан контакт
BitrixID int32 // id контакта в амо
Field string // значение поля
}

21
model/bitrixResp.go Normal file

@ -0,0 +1,21 @@
package model
type UserListBitrixResp struct {
Count int64 `json:"count"`
Items []BitrixAccountUser `json:"items"`
}
type UserBitrixListPipelinesResp struct {
Count int64 `json:"count"`
Items []PipelineBitrix `json:"items"`
}
type UserListBitrixStepsResp struct {
Items []StepBitrix `json:"items"`
Count int64 `json:"count"`
}
type UserListBitrixFieldsResp struct {
Count int64 `json:"count"`
Items []BitrixField `json:"items"`
}

78
model/bitrixTypes.go Normal file

@ -0,0 +1,78 @@
package model
type FieldsType string
const (
FieldTypeLead FieldsType = "CRM_LEAD"
FieldTypeCompany FieldsType = "CRM_COMPANY"
FieldTypeContact FieldsType = "CRM_CONTACT"
FieldTypeDeal FieldsType = "CRM_DEAL"
FieldTypeInvoiceOld FieldsType = "CRM_INVOICE"
FieldTypeInvoiceNew FieldsType = "CRM_SMART_INVOICE"
FieldTypeQuote FieldsType = "CRM_QUOTE"
FieldTypeRequisite FieldsType = "CRM_REQUISITE"
)
type IntegerEntityType int
const (
IntegerEntityTypeLead IntegerEntityType = 1 // воронки не поддерживает
IntegerEntityTypeCompany IntegerEntityType = 4
IntegerEntityTypeContact IntegerEntityType = 3
IntegerEntityTypeDeal IntegerEntityType = 2
IntegerEntityTypeInvoiceOld IntegerEntityType = 5 // может вернуть 400
IntegerEntityTypeInvoiceNew IntegerEntityType = 31
IntegerEntityTypeQuote IntegerEntityType = 7 // воронки не поддерживает
IntegerEntityTypeRequisite IntegerEntityType = 8 // может вернуть 400
)
type NameEntityType string
const (
NameEntityTypeLead NameEntityType = "LEAD"
NameEntityTypeCompany NameEntityType = "COMPANY"
NameEntityTypeContact NameEntityType = "CONTACT"
NameEntityTypeDeal NameEntityType = "DEAL"
NameEntityTypeInvoiceOld NameEntityType = "INVOICE"
NameEntityTypeInvoiceNew NameEntityType = "SMART_INVOICE"
NameEntityTypeQuote NameEntityType = "QUOTE"
NameEntityTypeRequisite NameEntityType = "REQUISITE"
)
type CompanyType string
const (
CompanyTypeCustomer CompanyType = "customer"
)
type BitrixIsDefault string
const (
BitrixIsDefaultY BitrixIsDefault = "Y"
BitrixIsDefaultN BitrixIsDefault = "N"
)
var CategoryArr = [4]IntegerEntityType{
IntegerEntityTypeCompany, IntegerEntityTypeContact, IntegerEntityTypeDeal, IntegerEntityTypeInvoiceNew,
}
type CustomFieldsType string
const (
StringCustomFieldsType CustomFieldsType = "string"
IntegerCustomFieldsType CustomFieldsType = "integer"
DoubleCustomFieldsType CustomFieldsType = "double"
BooleanCustomFieldsType CustomFieldsType = "boolean"
DatetimeCustomFieldsType CustomFieldsType = "datetime"
EnumerationCustomFieldsType CustomFieldsType = "enumeration"
IblockSectionCustomFieldsType CustomFieldsType = "iblock_section"
IblockElementCustomFieldsType CustomFieldsType = "iblock_element"
EmployeeCustomFieldsType CustomFieldsType = "employee"
CrmStatusCustomFieldsType CustomFieldsType = "crm_status"
CrmCustomFieldsType CustomFieldsType = "crm"
AddressCustomFieldsType CustomFieldsType = "address"
MoneyCustomFieldsType CustomFieldsType = "money"
UrlCustomFieldsType CustomFieldsType = "url"
FileCustomFieldsType CustomFieldsType = "file"
PenaTagCustomFieldsType CustomFieldsType = "crm_pena_tag"
)

888
repository/bitrix/bitrix.go Normal file

@ -0,0 +1,888 @@
package bitrix
import (
"context"
"database/sql"
"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"
)
type BitrixRepository struct {
queries *sqlcgen.Queries
pool *sql.DB
}
type Deps struct {
Queries *sqlcgen.Queries
Pool *sql.DB
}
func NewBitrixRepository(deps Deps) *BitrixRepository {
return &BitrixRepository{
queries: deps.Queries,
pool: deps.Pool,
}
}
// методы компании
func (r *BitrixRepository) GettingUserWithPagination(ctx context.Context, req *model.PaginationReq, accountID string) (*model.UserListBitrixResp, error) {
rows, err := r.queries.GetUsersBitrixWithPagination(ctx, sqlcgen.GetUsersBitrixWithPaginationParams{
Accountid: accountID,
Column2: req.Page,
Limit: req.Size,
})
if err != nil {
return nil, err
}
var users []model.BitrixAccountUser
var count int64
for _, row := range rows {
users = append(users, model.BitrixAccountUser{
ID: row.ID,
AccountID: row.Accountid,
BitrixIDUserID: row.Bitrixiduserid,
Name: row.Name,
LastName: row.Lastname,
SecondName: row.Secondname,
Title: row.Title,
Email: row.Email,
UFDepartment: row.Ufdepartment,
WorkPosition: row.Workposition,
CreatedAt: row.Createdat,
})
count = row.TotalCount
}
resp := model.UserListBitrixResp{
Count: count,
Items: users,
}
return &resp, nil
}
func (r *BitrixRepository) SoftDeleteAccount(ctx context.Context, accountID string) error {
err := r.queries.SoftDeleteBitrixAccount(ctx, accountID)
if err != nil {
return err
}
return nil
}
func (r *BitrixRepository) GetCurrentAccount(ctx context.Context, accountID string) (*model.BitrixAccount, error) {
row, err := r.queries.GetCurrentBitrixCompany(ctx, accountID)
if err != nil {
return nil, err
}
user := model.BitrixAccount{
ID: row.ID,
AccountID: row.Accountid,
BitrixID: row.Bitrixid,
CreatedAt: row.Createdat,
Subdomain: row.Subdomain,
}
_, err = r.queries.CheckExpiredBitrixToken(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 *BitrixRepository) UpdateCurrentAccount(ctx context.Context, user model.BitrixAccount) error {
err := r.queries.UpdateBitrixAccount(ctx, sqlcgen.UpdateBitrixAccountParams{
Accountid: user.AccountID,
Subdomain: user.Subdomain,
})
if err != nil {
return err
}
return nil
}
func (r *BitrixRepository) CreateAccount(ctx context.Context, userInfo model.BitrixAccount) error {
err := r.queries.CreateBitrixAccount(ctx, sqlcgen.CreateBitrixAccountParams{
Accountid: userInfo.AccountID,
Subdomain: userInfo.Subdomain,
Bitrixid: userInfo.BitrixID,
})
if err != nil {
return err
}
return nil
}
// методы пользователей
func (r *BitrixRepository) AddBitrixAccountUser(ctx context.Context, user model.BitrixAccountUser) error {
err := r.queries.AddBitrixAccountUser(ctx, sqlcgen.AddBitrixAccountUserParams{
Accountid: user.AccountID,
Bitrixiduserid: user.BitrixIDUserID,
Name: user.Name,
Lastname: user.LastName,
Secondname: user.SecondName,
Title: user.Title,
Email: user.Email,
Ufdepartment: user.UFDepartment,
Workposition: user.WorkPosition,
})
if err != nil {
return err
}
return nil
}
func (r *BitrixRepository) UpdateBitrixAccountUser(ctx context.Context, user model.BitrixAccountUser) error {
err := r.queries.UpdateBitrixAccountUser(ctx, sqlcgen.UpdateBitrixAccountUserParams{
Accountid: user.AccountID,
Bitrixiduserid: user.BitrixIDUserID,
Name: user.Name,
Lastname: user.LastName,
Secondname: user.SecondName,
Title: user.Title,
Email: user.Email,
Ufdepartment: user.UFDepartment,
Workposition: user.WorkPosition,
})
if err != nil {
return err
}
return nil
}
func (r *BitrixRepository) GetTokenByID(ctx context.Context, accountID string) (*model.Token, error) {
row, err := r.queries.GetBitrixTokenById(ctx, accountID)
if err != nil {
return nil, err
}
return &model.Token{
AccountID: row.Accountid,
RefreshToken: row.Refreshtoken,
AccessToken: row.Accesstoken,
AuthCode: row.Authcode,
Expiration: row.Expiration.Unix(),
CreatedAt: row.Createdat.Unix(),
}, nil
}
func (r *BitrixRepository) DeleteUsers(ctx context.Context, ids []int64) error {
err := r.queries.DeleteBitrixUsers(ctx, ids)
if err != nil {
return err
}
return nil
}
func (r *BitrixRepository) GetUserUsersByID(ctx context.Context, bitrixCompanyID string) ([]model.BitrixAccountUser, error) {
rows, err := r.queries.GetUserUsersByIDBitrix(ctx, bitrixCompanyID)
if err != nil {
return nil, err
}
var users []model.BitrixAccountUser
for _, row := range rows {
users = append(users, model.BitrixAccountUser{
ID: row.ID,
AccountID: row.Accountid,
BitrixIDUserID: row.Bitrixiduserid,
Name: row.Name,
LastName: row.Lastname,
SecondName: row.Secondname,
Title: row.Title,
Email: row.Email,
UFDepartment: row.Ufdepartment,
WorkPosition: row.Workposition,
CreatedAt: row.Createdat,
})
}
return users, nil
}
// методы webhook
func (r *BitrixRepository) WebhookCreate(ctx context.Context, tokens model.Token) error {
err := r.queries.CreateBitrixWebHook(ctx, sqlcgen.CreateBitrixWebHookParams{
Accountid: tokens.AccountID,
Refreshtoken: tokens.RefreshToken,
Accesstoken: tokens.AccessToken,
Authcode: tokens.AuthCode,
Expiration: time.Unix(tokens.Expiration, 0).In(time.Unix(tokens.CreatedAt, 0).Location()),
Createdat: time.Unix(tokens.CreatedAt, 0),
})
if err != nil {
return err
}
return nil
}
func (r *BitrixRepository) WebhookUpdate(ctx context.Context, token model.Token) error {
err := r.queries.WebhookBitrixUpdate(ctx, sqlcgen.WebhookBitrixUpdateParams{
Accesstoken: token.AccessToken,
Refreshtoken: token.RefreshToken,
Accountid: token.AccountID,
Column3: token.Expiration,
Column4: token.CreatedAt,
})
if err != nil {
return err
}
return nil
}
func (r *BitrixRepository) GetAllTokens(ctx context.Context) ([]model.Token, error) {
rows, err := r.queries.GetAllBitrixTokens(ctx)
if err != nil {
return nil, err
}
var tokens []model.Token
for _, row := range rows {
tokens = append(tokens, model.Token{
AccountID: row.Accountid,
AccessToken: row.Accesstoken,
RefreshToken: row.Refreshtoken,
AuthCode: row.Authcode,
Expiration: row.Expiration.Unix(),
CreatedAt: row.Createdat.Unix(),
})
}
return tokens, nil
}
func (r *BitrixRepository) WebhookDelete(ctx context.Context, bitrixID string) error {
err := r.queries.WebhookBitrixDelete(ctx, bitrixID)
if err != nil {
return err
}
return nil
}
// методы pipelines
func (r *BitrixRepository) GetPipelinesWithPagination(ctx context.Context, req *model.PaginationReq, accountID string) (*model.UserBitrixListPipelinesResp, error) {
rows, err := r.queries.GetBitrixPipelinesWithPagination(ctx, sqlcgen.GetBitrixPipelinesWithPaginationParams{
Accountid: accountID,
Column2: req.Page,
Limit: req.Size,
})
if err != nil {
return nil, err
}
var count int64
var pipelines []model.PipelineBitrix
for _, row := range rows {
count = row.TotalCount
pipelines = append(pipelines, model.PipelineBitrix{
ID: row.ID,
BitrixID: row.Bitrixid,
AccountID: row.Accountid,
Name: row.Name,
EntityTypeId: model.IntegerEntityType(row.Entitytypeid),
Createdat: row.Createdat.Unix(),
})
}
resp := model.UserBitrixListPipelinesResp{
Count: count,
Items: pipelines,
}
return &resp, nil
}
func (r *BitrixRepository) CheckPipelines(ctx context.Context, pipelines []model.PipelineBitrix) error {
dollar1, err := json.Marshal(pipelines)
if err != nil {
return err
}
rows, err := r.queries.CheckBitrixPipelines(ctx, dollar1)
if err != nil {
return err
}
if rows != nil {
var toUpdate []model.PipelineBitrix
for _, row := range rows {
to := model.PipelineBitrix{
BitrixID: row.Bitrixid,
AccountID: row.Accountid,
Name: row.Name,
EntityTypeId: model.IntegerEntityType(row.Entitytypeid),
}
toUpdate = append(toUpdate, to)
}
dollar1, err := json.Marshal(toUpdate)
if err != nil {
return err
}
err = r.queries.UpdateBitrixPipelines(ctx, dollar1)
if err != nil {
return err
}
}
return nil
}
func (r *BitrixRepository) DeletePipelines(ctx context.Context, ids []int64) error {
err := r.queries.DeleteBitrixPipelines(ctx, ids)
if err != nil {
return err
}
return nil
}
func (r *BitrixRepository) GetUserPipelinesByID(ctx context.Context, bitrixID string) ([]model.PipelineBitrix, error) {
rows, err := r.queries.GetUserBitrixPipelinesByID(ctx, bitrixID)
if err != nil {
return nil, err
}
var pipelines []model.PipelineBitrix
for _, row := range rows {
pipeline := model.PipelineBitrix{
ID: row.ID,
BitrixID: row.Bitrixid,
AccountID: row.Accountid,
Name: row.Name,
EntityTypeId: model.IntegerEntityType(row.Entitytypeid),
}
pipelines = append(pipelines, pipeline)
}
return pipelines, nil
}
// методы steps
func (r *BitrixRepository) GetStepsWithPagination(ctx context.Context, req *model.PaginationReq, bitrixID string) (*model.UserListBitrixStepsResp, error) {
rows, err := r.queries.GetBitrixStepsWithPagination(ctx, sqlcgen.GetBitrixStepsWithPaginationParams{
Accountid: bitrixID,
Column2: req.Page,
Limit: req.Size,
})
if err != nil {
return nil, err
}
var count int64
var steps []model.StepBitrix
for _, row := range rows {
count = row.TotalCount
steps = append(steps, model.StepBitrix{
ID: row.ID,
AccountID: row.Accountid,
BitrixID: row.Bitrixid,
EntityID: row.Entityid,
StatusID: row.Statusid,
Name: row.Name,
NameInit: row.Nameinit,
Color: row.Color,
PipelineID: row.Pipelineid,
Createdat: row.Createdat.Unix(),
})
}
resp := model.UserListBitrixStepsResp{
Count: count,
Items: steps,
}
return &resp, nil
}
// todo
func (r *BitrixRepository) CheckSteps(ctx context.Context, steps []model.StepBitrix) error {
dollar1, err := json.Marshal(steps)
if err != nil {
return err
}
rows, err := r.queries.CheckBitrixSteps(ctx, dollar1)
if err != nil {
return err
}
if rows != nil {
var toUpdate []model.StepBitrix
for _, row := range rows {
to := model.StepBitrix{
AccountID: row.Accountid,
BitrixID: row.Bitrixid,
Name: row.Name,
EntityID: row.Entityid,
StatusID: row.Statusid,
NameInit: row.Nameinit,
Color: row.Color,
PipelineID: row.Pipelineid,
}
toUpdate = append(toUpdate, to)
}
dollar1, err := json.Marshal(toUpdate)
if err != nil {
return err
}
err = r.queries.UpdateBitrixSteps(ctx, dollar1)
if err != nil {
return err
}
}
return nil
}
func (r *BitrixRepository) DeleteSteps(ctx context.Context, ids []int64) error {
err := r.queries.DeleteBitrixSteps(ctx, ids)
if err != nil {
return err
}
return nil
}
func (r *BitrixRepository) GetUserStepsByID(ctx context.Context, bitrixID string) ([]model.StepBitrix, error) {
rows, err := r.queries.GetUserBitrixStepsByID(ctx, bitrixID)
if err != nil {
return nil, err
}
var steps []model.StepBitrix
for _, row := range rows {
steps = append(steps, model.StepBitrix{
ID: row.ID,
AccountID: row.Accountid,
BitrixID: row.Bitrixid,
StatusID: row.Statusid,
EntityID: row.Entityid,
Name: row.Name,
NameInit: row.Nameinit,
Color: row.Color,
PipelineID: row.Pipelineid,
})
}
return steps, nil
}
// методы tags todo
// методы fields
func (r *BitrixRepository) GetFieldsWithPagination(ctx context.Context, req *model.PaginationReq, accountID string) (*model.UserListBitrixFieldsResp, error) {
rows, err := r.queries.GetBitrixFieldsWithPagination(ctx, sqlcgen.GetBitrixFieldsWithPaginationParams{
Accountid: accountID,
Column2: req.Page,
Limit: req.Size,
})
if err != nil {
return nil, err
}
var count int64
var fields []model.BitrixField
for _, row := range rows {
count = row.TotalCount
var entityID model.FieldsType
v := string(row.Entityid.([]byte))
entityID = model.FieldsType(v)
var fieldType model.CustomFieldsType
f := string(row.Fieldtype.([]byte))
fieldType = model.CustomFieldsType(f)
fields = append(fields, model.BitrixField{
ID: row.ID,
AccountID: row.Accountid,
EntityID: entityID,
FieldName: row.Fieldname,
EditFromLabel: row.Editfromlabel,
FieldType: fieldType,
Createdat: row.Createdat.Unix(),
BitrixID: row.Bitrixid,
})
}
resp := model.UserListBitrixFieldsResp{
Count: count,
Items: fields,
}
return &resp, nil
}
func (r *BitrixRepository) CheckFields(ctx context.Context, fields []model.BitrixField, accountID string) error {
column2, err := json.Marshal(fields)
if err != nil {
return err
}
rows, err := r.queries.CheckBitrixFields(ctx, sqlcgen.CheckBitrixFieldsParams{
Accountid: accountID,
Column2: column2,
})
if err != nil {
return err
}
if rows != nil {
var toUpdate []model.BitrixField
for _, row := range rows {
var entityID model.FieldsType
v := string(row.Entityid.([]byte))
entityID = model.FieldsType(v)
var fieldType model.CustomFieldsType
f := string(row.Fieldtype.([]byte))
fieldType = model.CustomFieldsType(f)
toUpdate = append(toUpdate, model.BitrixField{
AccountID: row.Accountid,
EntityID: entityID,
FieldName: row.Fieldname,
EditFromLabel: row.Editfromlabel,
FieldType: fieldType,
BitrixID: row.Bitrixid,
})
}
dollar1, err := json.Marshal(toUpdate)
if err != nil {
return err
}
err = r.queries.UpdateBitrixFields(ctx, dollar1)
if err != nil {
return err
}
}
return nil
}
func (r *BitrixRepository) GetUserFieldsByID(ctx context.Context, bitrixID string) ([]model.BitrixField, error) {
rows, err := r.queries.GetUserBitrixFieldsByID(ctx, bitrixID)
if err != nil {
return nil, err
}
var fields []model.BitrixField
for _, row := range rows {
var entityID model.FieldsType
v := string(row.Entityid.([]byte))
entityID = model.FieldsType(v)
var fieldType model.CustomFieldsType
f := string(row.Fieldtype.([]byte))
fieldType = model.CustomFieldsType(f)
fields = append(fields, model.BitrixField{
ID: row.ID,
AccountID: row.Accountid,
FieldName: row.Fieldname,
EditFromLabel: row.Editfromlabel,
Createdat: row.Createdat.Unix(),
EntityID: entityID,
FieldType: fieldType,
BitrixID: row.Bitrixid,
})
}
return fields, err
}
func (r *BitrixRepository) DeleteFields(ctx context.Context, ids []int64) error {
err := r.queries.DeleteBitrixFields(ctx, ids)
if err != nil {
return err
}
return nil
}
// todo mb by name? bec in create field return int id, but getting list return string ))
func (r *BitrixRepository) GetFieldByID(ctx context.Context, bitrixID string) (*model.BitrixField, error) {
row, err := r.queries.GetBitrixFieldByID(ctx, bitrixID)
if err != nil {
return nil, err
}
var entityID model.FieldsType
v := string(row.Entityid.([]byte))
entityID = model.FieldsType(v)
var fieldType model.CustomFieldsType
f := string(row.Fieldtype.([]byte))
fieldType = model.CustomFieldsType(f)
return &model.BitrixField{
ID: row.ID,
AccountID: row.Accountid,
FieldName: row.Fieldname,
EditFromLabel: row.Editfromlabel,
Createdat: row.Createdat.Unix(),
EntityID: entityID,
FieldType: fieldType,
BitrixID: row.Bitrixid,
}, nil
}
// методы rules
func (r *BitrixRepository) ChangeQuizSettings(ctx context.Context, request *model.BitrixRulesReq, accountID string, quizID int) error {
jsonFieldRule, err := json.Marshal(request.FieldsRule)
if err != nil {
return err
}
jsonTagsToAdd, err := json.Marshal(request.TagsToAdd)
if err != nil {
return err
}
_, err = r.queries.ChangeBitrixQuizSettings(ctx, sqlcgen.ChangeBitrixQuizSettingsParams{
Performerid: request.PerformerID,
Pipelineid: request.PipelineID,
Typeid: request.TypeID,
Stageid: request.StageID,
Sourceid: request.SourceID,
Fieldsrule: jsonFieldRule,
Tagstoadd: jsonTagsToAdd,
Leadflag: request.LeadFlag,
Accountid: accountID,
Quizid: int32(quizID),
Statusid: request.StatusID,
})
if err != nil {
return err
}
return nil
}
func (r *BitrixRepository) SetQuizSettings(ctx context.Context, request *model.BitrixRulesReq, accountID string, quizID int) error {
jsonFieldRule, err := json.Marshal(request.FieldsRule)
if err != nil {
return err
}
jsonTagsToAdd, err := json.Marshal(request.TagsToAdd)
if err != nil {
return err
}
_, err = r.queries.SetBitrixQuizSettings(ctx, sqlcgen.SetBitrixQuizSettingsParams{
Performerid: request.PerformerID,
Pipelineid: request.PipelineID,
Typeid: request.TypeID,
Stageid: request.StageID,
Sourceid: request.SourceID,
Fieldsrule: jsonFieldRule,
Tagstoadd: jsonTagsToAdd,
Accountid: accountID,
Quizid: int32(quizID),
Leadflag: request.LeadFlag,
Statusid: request.StatusID,
})
if err != nil {
return err
}
return nil
}
func (r *BitrixRepository) GettingQuizRules(ctx context.Context, quizID int) (*model.BitrixRule, error) {
row, err := r.queries.GetBitrixQuizRule(ctx, int32(quizID))
if err != nil {
return nil, err
}
var fieldsRule model.BitrixFieldRules
err = json.Unmarshal(row.Fieldsrule, &fieldsRule)
if err != nil {
return nil, err
}
var tagsToAdd model.TagsToAdd
err = json.Unmarshal(row.Tagstoadd, &tagsToAdd)
if err != nil {
return nil, err
}
return &model.BitrixRule{
ID: row.ID,
AccountID: row.Accountid,
QuizID: row.Quizid,
PerformerID: row.Performerid,
PipelineID: row.Pipelineid,
TypeID: row.Typeid,
StageID: row.Stageid,
SourceID: row.Sourceid,
FieldsRule: fieldsRule,
TagsToAdd: tagsToAdd,
LeadFlag: row.Leadflag,
StatusID: row.Statusid,
}, nil
}
func (r *BitrixRepository) UpdateFieldRules(ctx context.Context, fieldRules model.BitrixFieldRules, accountID string, quizID int32) error {
jsonFieldsRule, err := json.Marshal(fieldRules)
if err != nil {
return err
}
err = r.queries.UpdateBitrixFieldRules(ctx, sqlcgen.UpdateBitrixFieldRulesParams{
Fieldsrule: jsonFieldsRule,
Accountid: accountID,
Quizid: quizID,
})
if err != nil {
return err
}
return nil
}
// todo need check
func (r *BitrixRepository) GettingBitrixUsersTrueResults(ctx context.Context) ([]model.BitrixUsersTrueResults, error) {
rows, err := r.queries.GettingBitrixUsersTrueResults(ctx)
if err != nil {
return nil, err
}
var results []model.BitrixUsersTrueResults
for _, row := range rows {
var fieldsRule model.BitrixFieldRules
err = json.Unmarshal(row.Fieldsrule, &fieldsRule)
if err != nil {
return nil, err
}
var utm model.UTMSavingMap
err = json.Unmarshal(row.Utm.([]byte), &utm)
if err != nil {
return nil, err
}
var tagsToAdd model.TagsToAdd
err = json.Unmarshal(row.Tagstoadd, &tagsToAdd)
if err != nil {
return nil, err
}
result := model.BitrixUsersTrueResults{
QuizID: row.QuizID,
AnswerID: row.ID,
Result: row.Result.Bool,
QuestionID: row.QuestionID,
Content: row.Content.String,
Session: row.Session.String,
AccessToken: row.Accesstoken,
AmoAccountID: row.Accountid,
UTMs: utm,
FieldsRule: fieldsRule,
TagsToAdd: tagsToAdd,
PerformerID: row.Performerid,
TypeID: row.Typeid,
StageID: row.Stageid,
SourceID: row.Sourceid,
PipelineID: row.Pipelineid,
PerformerName: row.PerformerName,
SubDomain: row.Subdomain,
QuizAccountID: row.Accountid_2,
LeadFlag: row.Leadflag,
StatusID: row.Statusid,
}
results = append(results, result)
}
return results, nil
}
// методы bitrixCRMStatuses todo
type SaveDealBitrixDeps struct {
DealID int32
AnswerID int64
Status string
AccessToken string
}
func (r *BitrixRepository) SaveDealBitrixStatus(ctx context.Context, deps SaveDealBitrixDeps) error {
err := r.queries.SettingDealBitrixStatus(ctx, sqlcgen.SettingDealBitrixStatusParams{
Dealid: deps.DealID,
Answerid: deps.AnswerID,
Status: deps.Status,
Accesstoken: deps.AccessToken,
})
if err != nil {
return err
}
return nil
}
// методы для contact в амо
func (r *BitrixRepository) GetExistingContactBitrix(ctx context.Context, accountID string, fields []string) (map[int32][]model.ContactBitrix, error) {
rows, err := r.queries.GetExistingContactBitrix(ctx, sqlcgen.GetExistingContactBitrixParams{
Accountid: accountID,
Column2: fields,
})
if err != nil {
if err == sql.ErrNoRows {
return nil, pj_errors.ErrNotFound
}
return nil, err
}
result := make(map[int32][]model.ContactBitrix)
for _, row := range rows {
result[row.Bitrixid] = append(result[row.Bitrixid], model.ContactBitrix{
ID: row.ID,
BitrixID: row.Bitrixid,
AccountID: row.Accountid,
Field: row.Field,
})
}
return result, nil
}
func (r *BitrixRepository) InsertContactBitrix(ctx context.Context, val model.ContactBitrix) (int32, error) {
amoID, err := r.queries.InsertContactBitrix(ctx, sqlcgen.InsertContactBitrixParams{
Accountid: val.AccountID,
Bitrixid: val.BitrixID,
Field: val.Field,
})
if err != nil {
return 0, err
}
return amoID, err
}
func (r *BitrixRepository) UpdateBitrixContact(ctx context.Context, id int64, field string, newBitrixID int32) error {
err := r.queries.UpdateBitrixContact(ctx, sqlcgen.UpdateBitrixContactParams{
Field: field,
ID: id,
Bitrixid: newBitrixID,
})
if err != nil {
return err
}
return nil
}