diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a426e2..e4f8d91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,3 +2,4 @@ - ветка vlangTG - создание миграций для добавления таблицы интеграции и с ботом для телеги и таблицы текущего статуса прохождения опроса через телегабот. и всякие энамы вокруг этого - ветка chMigrate: миграция сложных запросов на LTV для промокода и мини партнёрки для перехода по quizLogo из сложных походов по внутренней сети на получение данных из clickhouse +- ветка bitrix: - все необходимые методы dal и запросы необходимые для работы интеграции с битриксом diff --git a/dal/dal.go b/dal/dal.go index a5fa76d..f68de2e 100644 --- a/dal/dal.go +++ b/dal/dal.go @@ -14,6 +14,7 @@ import ( "gitea.pena/SQuiz/common/repository/amo" "gitea.pena/SQuiz/common/repository/answer" "gitea.pena/SQuiz/common/repository/question" + "gitea.pena/SQuiz/common/repository/bitrix" "gitea.pena/SQuiz/common/repository/quiz" "gitea.pena/SQuiz/common/repository/result" "gitea.pena/SQuiz/common/repository/statistics" @@ -199,6 +200,75 @@ func (d *AmoDal) Close(ctx context.Context) error { 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 { conn *sql.DB StatisticClickRepo *statistics.StatisticClick diff --git a/dal/db_query/queries.sql b/dal/db_query/queries.sql index 6fb8d5c..16d01c9 100644 --- a/dal/db_query/queries.sql +++ b/dal/db_query/queries.sql @@ -1094,3 +1094,311 @@ SELECT accountid FROM quiz WHERE id = $1 AND accountid = $2; -- name: CheckLeadTargetOwner :one 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; diff --git a/dal/schema/000021_init.down.sql b/dal/schema/000021_init.down.sql index 24bee9c..1324e47 100644 --- a/dal/schema/000021_init.down.sql +++ b/dal/schema/000021_init.down.sql @@ -1 +1,35 @@ -ALTER TABLE answer DROP COLUMN IF EXISTS version; \ No newline at end of file +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; diff --git a/dal/schema/000021_init.up.sql b/dal/schema/000021_init.up.sql index aa9cfa1..d28c75e 100644 --- a/dal/schema/000021_init.up.sql +++ b/dal/schema/000021_init.up.sql @@ -1 +1,149 @@ -ALTER TABLE answer ADD COLUMN version integer NOT NULL default 0; \ No newline at end of file +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; diff --git a/dal/sqlcgen/models.go b/dal/sqlcgen/models.go index 7874091..5d485b5 100644 --- a/dal/sqlcgen/models.go +++ b/dal/sqlcgen/models.go @@ -69,6 +69,84 @@ type Answer struct { Version int32 `db:"version" json:"version"` } +type Bitrixaccount struct { + ID int64 `db:"id" json:"id"` + Accountid string `db:"accountid" json:"accountid"` + Bitrixid string `db:"bitrixid" json:"bitrixid"` + Deleted bool `db:"deleted" json:"deleted"` + Createdat time.Time `db:"createdat" json:"createdat"` + Subdomain string `db:"subdomain" json:"subdomain"` +} + +type Bitrixaccountuser struct { + ID int64 `db:"id" json:"id"` + Accountid string `db:"accountid" json:"accountid"` + Bitrixiduserid string `db:"bitrixiduserid" json:"bitrixiduserid"` + Name string `db:"name" json:"name"` + Lastname string `db:"lastname" json:"lastname"` + Secondname string `db:"secondname" json:"secondname"` + Title string `db:"title" json:"title"` + Email string `db:"email" json:"email"` + Ufdepartment []int32 `db:"ufdepartment" json:"ufdepartment"` + Workposition string `db:"workposition" json:"workposition"` + Deleted bool `db:"deleted" json:"deleted"` + Createdat time.Time `db:"createdat" json:"createdat"` +} + +type Bitrixcontact struct { + ID int64 `db:"id" json:"id"` + Accountid string `db:"accountid" json:"accountid"` + Bitrixid int32 `db:"bitrixid" json:"bitrixid"` + Field string `db:"field" json:"field"` +} + +type Bitrixcrmstatus struct { + ID int64 `db:"id" json:"id"` + Accountid string `db:"accountid" json:"accountid"` + Dealid int32 `db:"dealid" json:"dealid"` + Answerid int64 `db:"answerid" json:"answerid"` + Status string `db:"status" json:"status"` + Createdat time.Time `db:"createdat" json:"createdat"` +} + +type Bitrixfield struct { + ID int64 `db:"id" json:"id"` + Bitrixid string `db:"bitrixid" json:"bitrixid"` + Accountid string `db:"accountid" json:"accountid"` + Entityid interface{} `db:"entityid" json:"entityid"` + Fieldname string `db:"fieldname" json:"fieldname"` + Editfromlabel string `db:"editfromlabel" json:"editfromlabel"` + Fieldtype interface{} `db:"fieldtype" json:"fieldtype"` + Deleted bool `db:"deleted" json:"deleted"` + Createdat time.Time `db:"createdat" json:"createdat"` +} + +type Bitrixrule struct { + ID int64 `db:"id" json:"id"` + Accountid string `db:"accountid" json:"accountid"` + Quizid int32 `db:"quizid" json:"quizid"` + Performerid string `db:"performerid" json:"performerid"` + Pipelineid int32 `db:"pipelineid" json:"pipelineid"` + Typeid string `db:"typeid" json:"typeid"` + Stageid string `db:"stageid" json:"stageid"` + Sourceid string `db:"sourceid" json:"sourceid"` + Statusid string `db:"statusid" json:"statusid"` + Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"` + Tagstoadd json.RawMessage `db:"tagstoadd" json:"tagstoadd"` + Deleted bool `db:"deleted" json:"deleted"` + Createdat time.Time `db:"createdat" json:"createdat"` + Leadflag bool `db:"leadflag" json:"leadflag"` +} + +type Bitrixtoken struct { + Accountid string `db:"accountid" json:"accountid"` + Refreshtoken string `db:"refreshtoken" json:"refreshtoken"` + Accesstoken string `db:"accesstoken" json:"accesstoken"` + Authcode string `db:"authcode" json:"authcode"` + Expiration time.Time `db:"expiration" json:"expiration"` + Createdat time.Time `db:"createdat" json:"createdat"` +} + type Field struct { ID int64 `db:"id" json:"id"` Amoid int32 `db:"amoid" json:"amoid"` @@ -102,6 +180,16 @@ type Pipeline struct { Createdat sql.NullTime `db:"createdat" json:"createdat"` } +type Pipelinebitrix struct { + ID int64 `db:"id" json:"id"` + Bitrixid int32 `db:"bitrixid" json:"bitrixid"` + Accountid string `db:"accountid" json:"accountid"` + Name string `db:"name" json:"name"` + Entitytypeid int32 `db:"entitytypeid" json:"entitytypeid"` + Deleted bool `db:"deleted" json:"deleted"` + Createdat time.Time `db:"createdat" json:"createdat"` +} + type Privilege struct { ID int32 `db:"id" json:"id"` Privilegeid string `db:"privilegeid" json:"privilegeid"` @@ -183,6 +271,20 @@ type Step struct { Createdat sql.NullTime `db:"createdat" json:"createdat"` } +type Stepbitrix struct { + ID int64 `db:"id" json:"id"` + Accountid string `db:"accountid" json:"accountid"` + Bitrixid string `db:"bitrixid" json:"bitrixid"` + Entityid string `db:"entityid" json:"entityid"` + Statusid string `db:"statusid" json:"statusid"` + Name string `db:"name" json:"name"` + Nameinit string `db:"nameinit" json:"nameinit"` + Color string `db:"color" json:"color"` + Pipelineid int32 `db:"pipelineid" json:"pipelineid"` + Deleted bool `db:"deleted" json:"deleted"` + Createdat time.Time `db:"createdat" json:"createdat"` +} + type Tag struct { ID int64 `db:"id" json:"id"` Amoid int32 `db:"amoid" json:"amoid"` diff --git a/dal/sqlcgen/queries.sql.go b/dal/sqlcgen/queries.sql.go index b2af9b0..f7fd55a 100644 --- a/dal/sqlcgen/queries.sql.go +++ b/dal/sqlcgen/queries.sql.go @@ -79,6 +79,38 @@ func (q *Queries) AddAmoAccountUser(ctx context.Context, arg AddAmoAccountUserPa return err } +const addBitrixAccountUser = `-- 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) +` + +type AddBitrixAccountUserParams struct { + 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"` +} + +func (q *Queries) AddBitrixAccountUser(ctx context.Context, arg AddBitrixAccountUserParams) error { + _, err := q.db.ExecContext(ctx, addBitrixAccountUser, + arg.Accountid, + arg.Bitrixiduserid, + arg.Name, + arg.Lastname, + arg.Secondname, + arg.Title, + arg.Email, + pq.Array(arg.Ufdepartment), + arg.Workposition, + ) + return err +} + const allServiceStatistics = `-- name: AllServiceStatistics :one WITH Registrations AS ( SELECT COUNT(*) AS registration_count @@ -133,6 +165,46 @@ func (q *Queries) ArchiveQuiz(ctx context.Context, arg ArchiveQuizParams) error return err } +const changeBitrixQuizSettings = `-- 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 +` + +type ChangeBitrixQuizSettingsParams struct { + 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"` + Leadflag bool `db:"leadflag" json:"leadflag"` + Accountid string `db:"accountid" json:"accountid"` + Quizid int32 `db:"quizid" json:"quizid"` +} + +func (q *Queries) ChangeBitrixQuizSettings(ctx context.Context, arg ChangeBitrixQuizSettingsParams) (int64, error) { + row := q.db.QueryRowContext(ctx, changeBitrixQuizSettings, + arg.Performerid, + arg.Pipelineid, + arg.Typeid, + arg.Stageid, + arg.Sourceid, + arg.Statusid, + arg.Fieldsrule, + arg.Tagstoadd, + arg.Leadflag, + arg.Accountid, + arg.Quizid, + ) + var id int64 + err := row.Scan(&id) + return id, err +} + const changeQuizSettings = `-- name: ChangeQuizSettings :one UPDATE rules SET PerformerID = $1,PipelineID = $2,StepID = $3,FieldsRule = $4, TagsToAdd=$5 @@ -183,6 +255,257 @@ func (q *Queries) CheckAndAddDefault(ctx context.Context, arg CheckAndAddDefault return err } +const checkBitrixFields = `-- 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 id, bitrixid, accountid, entityid, fieldname, editfromlabel, fieldtype, deleted, createdat +) +SELECT nf.bitrixid, nf.accountid, nf.entityid, nf.fieldname, nf.editfromlabel, nf.fieldtype, nf.createdat, ud.BitrixID AS AccountID +FROM new_fields nf + JOIN user_data ud ON true +WHERE NOT EXISTS ( + SELECT id, ins.bitrixid, accountid, entityid, fieldname, editfromlabel, fieldtype, deleted, createdat, ud.bitrixid + 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 +) +` + +type CheckBitrixFieldsParams struct { + Accountid string `db:"accountid" json:"accountid"` + Column2 json.RawMessage `db:"column_2" json:"column_2"` +} + +type CheckBitrixFieldsRow struct { + 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"` + Createdat interface{} `db:"createdat" json:"createdat"` + Accountid_2 string `db:"accountid_2" json:"accountid_2"` +} + +func (q *Queries) CheckBitrixFields(ctx context.Context, arg CheckBitrixFieldsParams) ([]CheckBitrixFieldsRow, error) { + rows, err := q.db.QueryContext(ctx, checkBitrixFields, arg.Accountid, arg.Column2) + if err != nil { + return nil, err + } + defer rows.Close() + var items []CheckBitrixFieldsRow + for rows.Next() { + var i CheckBitrixFieldsRow + if err := rows.Scan( + &i.Bitrixid, + &i.Accountid, + &i.Entityid, + &i.Fieldname, + &i.Editfromlabel, + &i.Fieldtype, + &i.Createdat, + &i.Accountid_2, + ); 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 checkBitrixPipelines = `-- 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 id, bitrixid, accountid, name, entitytypeid, deleted, createdat +) +SELECT np.bitrixid, np.accountid, np.name, np.entitytypeid, np.createdat +FROM new_pipelines np +WHERE NOT EXISTS ( + SELECT id, bitrixid, accountid, name, entitytypeid, deleted, createdat + FROM inserted_pipelines ins + WHERE ins.BitrixID = np.BitrixID AND ins.AccountID = np.AccountID +) +` + +type CheckBitrixPipelinesRow struct { + Bitrixid int32 `db:"bitrixid" json:"bitrixid"` + Accountid string `db:"accountid" json:"accountid"` + Name string `db:"name" json:"name"` + Entitytypeid int32 `db:"entitytypeid" json:"entitytypeid"` + Createdat interface{} `db:"createdat" json:"createdat"` +} + +func (q *Queries) CheckBitrixPipelines(ctx context.Context, dollar_1 json.RawMessage) ([]CheckBitrixPipelinesRow, error) { + rows, err := q.db.QueryContext(ctx, checkBitrixPipelines, dollar_1) + if err != nil { + return nil, err + } + defer rows.Close() + var items []CheckBitrixPipelinesRow + for rows.Next() { + var i CheckBitrixPipelinesRow + if err := rows.Scan( + &i.Bitrixid, + &i.Accountid, + &i.Name, + &i.Entitytypeid, + &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 checkBitrixSteps = `-- 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 id, accountid, bitrixid, entityid, statusid, name, nameinit, color, pipelineid, deleted, createdat +) +SELECT ns.bitrixid, ns.pipelineid, ns.accountid, ns.entityid, ns.statusid, ns.name, ns.nameinit, ns.color, ns.createdat +FROM new_steps ns +WHERE NOT EXISTS ( + SELECT id, accountid, bitrixid, entityid, statusid, name, nameinit, color, pipelineid, deleted, createdat + FROM inserted_steps ins + WHERE ins.BitrixID = ns.BitrixID AND ins.AccountID = ns.AccountID +) +` + +type CheckBitrixStepsRow struct { + Bitrixid string `db:"bitrixid" json:"bitrixid"` + Pipelineid int32 `db:"pipelineid" json:"pipelineid"` + Accountid string `db:"accountid" json:"accountid"` + 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"` + Createdat interface{} `db:"createdat" json:"createdat"` +} + +func (q *Queries) CheckBitrixSteps(ctx context.Context, dollar_1 json.RawMessage) ([]CheckBitrixStepsRow, error) { + rows, err := q.db.QueryContext(ctx, checkBitrixSteps, dollar_1) + if err != nil { + return nil, err + } + defer rows.Close() + var items []CheckBitrixStepsRow + for rows.Next() { + var i CheckBitrixStepsRow + if err := rows.Scan( + &i.Bitrixid, + &i.Pipelineid, + &i.Accountid, + &i.Entityid, + &i.Statusid, + &i.Name, + &i.Nameinit, + &i.Color, + &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 checkExpiredBitrixToken = `-- name: CheckExpiredBitrixToken :one +SELECT accountid, refreshtoken, accesstoken, authcode, expiration, createdat FROM BitrixTokens WHERE AccountID = $1 AND Expiration <= NOW() +` + +func (q *Queries) CheckExpiredBitrixToken(ctx context.Context, accountid string) (Bitrixtoken, error) { + row := q.db.QueryRowContext(ctx, checkExpiredBitrixToken, accountid) + var i Bitrixtoken + err := row.Scan( + &i.Accountid, + &i.Refreshtoken, + &i.Accesstoken, + &i.Authcode, + &i.Expiration, + &i.Createdat, + ) + return i, err +} + const checkExpiredToken = `-- name: CheckExpiredToken :one SELECT accountid, refreshtoken, accesstoken, authcode, expiration, createdat FROM tokens WHERE AccountID = $1 AND Expiration <= NOW() ` @@ -755,6 +1078,48 @@ func (q *Queries) CreateAmoAccount(ctx context.Context, arg CreateAmoAccountPara return err } +const createBitrixAccount = `-- name: CreateBitrixAccount :exec +INSERT INTO BitrixAccounts (AccountID, BitrixID, Subdomain) +VALUES ($1, $2, $3) +` + +type CreateBitrixAccountParams struct { + Accountid string `db:"accountid" json:"accountid"` + Bitrixid string `db:"bitrixid" json:"bitrixid"` + Subdomain string `db:"subdomain" json:"subdomain"` +} + +func (q *Queries) CreateBitrixAccount(ctx context.Context, arg CreateBitrixAccountParams) error { + _, err := q.db.ExecContext(ctx, createBitrixAccount, arg.Accountid, arg.Bitrixid, arg.Subdomain) + return err +} + +const createBitrixWebHook = `-- name: CreateBitrixWebHook :exec +INSERT INTO BitrixTokens (AccountID, RefreshToken, AccessToken, AuthCode, Expiration, CreatedAt) +VALUES ($1, $2, $3, $4, $5, $6) +` + +type CreateBitrixWebHookParams 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"` +} + +func (q *Queries) CreateBitrixWebHook(ctx context.Context, arg CreateBitrixWebHookParams) error { + _, err := q.db.ExecContext(ctx, createBitrixWebHook, + arg.Accountid, + arg.Refreshtoken, + arg.Accesstoken, + arg.Authcode, + arg.Expiration, + arg.Createdat, + ) + return err +} + const createLeadTarget = `-- name: CreateLeadTarget :one INSERT INTO leadtarget (accountID,type,quizID,target,InviteLink) VALUES ($1,$2,$3,$4,$5) RETURNING id, accountid, type, quizid, target, invitelink, deleted, createdat ` @@ -875,6 +1240,42 @@ func (q *Queries) DeleteAccountById(ctx context.Context, id uuid.UUID) error { return err } +const deleteBitrixFields = `-- name: DeleteBitrixFields :exec +UPDATE BitrixFields SET Deleted = true WHERE ID = ANY($1::bigint[]) +` + +func (q *Queries) DeleteBitrixFields(ctx context.Context, dollar_1 []int64) error { + _, err := q.db.ExecContext(ctx, deleteBitrixFields, pq.Array(dollar_1)) + return err +} + +const deleteBitrixPipelines = `-- name: DeleteBitrixPipelines :exec +UPDATE PipelineBitrix SET Deleted = true WHERE ID = ANY($1::bigint[]) +` + +func (q *Queries) DeleteBitrixPipelines(ctx context.Context, dollar_1 []int64) error { + _, err := q.db.ExecContext(ctx, deleteBitrixPipelines, pq.Array(dollar_1)) + return err +} + +const deleteBitrixSteps = `-- name: DeleteBitrixSteps :exec +UPDATE StepBitrix SET Deleted = true WHERE ID = ANY($1::bigint[]) +` + +func (q *Queries) DeleteBitrixSteps(ctx context.Context, dollar_1 []int64) error { + _, err := q.db.ExecContext(ctx, deleteBitrixSteps, pq.Array(dollar_1)) + return err +} + +const deleteBitrixUsers = `-- name: DeleteBitrixUsers :exec +UPDATE BitrixAccountUsers SET Deleted = true WHERE ID = ANY($1::bigint[]) +` + +func (q *Queries) DeleteBitrixUsers(ctx context.Context, dollar_1 []int64) error { + _, err := q.db.ExecContext(ctx, deleteBitrixUsers, pq.Array(dollar_1)) + return err +} + const deleteFields = `-- name: DeleteFields :exec UPDATE fields SET Deleted = true WHERE ID = ANY($1::bigint[]) ` @@ -1464,6 +1865,40 @@ func (q *Queries) GetAllAnswersByQuizID(ctx context.Context, session sql.NullStr return items, nil } +const getAllBitrixTokens = `-- name: GetAllBitrixTokens :many +SELECT accountid, refreshtoken, accesstoken, authcode, expiration, createdat FROM BitrixTokens +` + +func (q *Queries) GetAllBitrixTokens(ctx context.Context) ([]Bitrixtoken, error) { + rows, err := q.db.QueryContext(ctx, getAllBitrixTokens) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Bitrixtoken + for rows.Next() { + var i Bitrixtoken + if err := rows.Scan( + &i.Accountid, + &i.Refreshtoken, + &i.Accesstoken, + &i.Authcode, + &i.Expiration, + &i.Createdat, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const getAllCompanyUsers = `-- name: GetAllCompanyUsers :many SELECT id, amoid, amouserid, name, email, role, "Group", deleted, createdat FROM usersamo WHERE amoid = $1 AND deleted = false ` @@ -1571,6 +2006,277 @@ func (q *Queries) GetAllTokens(ctx context.Context) ([]Token, error) { return items, nil } +const getBitrixFieldByID = `-- name: GetBitrixFieldByID :one +SELECT id, bitrixid, accountid, entityid, fieldname, editfromlabel, fieldtype, deleted, createdat FROM BitrixFields WHERE BitrixID = $1 AND Deleted = false +` + +func (q *Queries) GetBitrixFieldByID(ctx context.Context, bitrixid string) (Bitrixfield, error) { + row := q.db.QueryRowContext(ctx, getBitrixFieldByID, bitrixid) + var i Bitrixfield + err := row.Scan( + &i.ID, + &i.Bitrixid, + &i.Accountid, + &i.Entityid, + &i.Fieldname, + &i.Editfromlabel, + &i.Fieldtype, + &i.Deleted, + &i.Createdat, + ) + return i, err +} + +const getBitrixFieldsWithPagination = `-- name: GetBitrixFieldsWithPagination :many +WITH user_data AS ( + SELECT BitrixID FROM BitrixAccounts WHERE BitrixAccounts.AccountID = $1 AND BitrixAccounts.Deleted = false +) +SELECT f.id, f.bitrixid, f.accountid, f.entityid, f.fieldname, f.editfromlabel, f.fieldtype, f.deleted, f.createdat, 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 +` + +type GetBitrixFieldsWithPaginationParams struct { + Accountid string `db:"accountid" json:"accountid"` + Column2 interface{} `db:"column_2" json:"column_2"` + Limit int32 `db:"limit" json:"limit"` +} + +type GetBitrixFieldsWithPaginationRow 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"` + TotalCount int64 `db:"total_count" json:"total_count"` +} + +func (q *Queries) GetBitrixFieldsWithPagination(ctx context.Context, arg GetBitrixFieldsWithPaginationParams) ([]GetBitrixFieldsWithPaginationRow, error) { + rows, err := q.db.QueryContext(ctx, getBitrixFieldsWithPagination, arg.Accountid, arg.Column2, arg.Limit) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetBitrixFieldsWithPaginationRow + for rows.Next() { + var i GetBitrixFieldsWithPaginationRow + if err := rows.Scan( + &i.ID, + &i.Bitrixid, + &i.Accountid, + &i.Entityid, + &i.Fieldname, + &i.Editfromlabel, + &i.Fieldtype, + &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 getBitrixPipelinesWithPagination = `-- name: GetBitrixPipelinesWithPagination :many +WITH user_data AS ( + SELECT BitrixID FROM BitrixAccounts WHERE BitrixAccounts.AccountID = $1 AND BitrixAccounts.Deleted = false +) +SELECT p.id, p.bitrixid, p.accountid, p.name, p.entitytypeid, p.deleted, p.createdat, 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 +` + +type GetBitrixPipelinesWithPaginationParams struct { + Accountid string `db:"accountid" json:"accountid"` + Column2 interface{} `db:"column_2" json:"column_2"` + Limit int32 `db:"limit" json:"limit"` +} + +type GetBitrixPipelinesWithPaginationRow 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"` + TotalCount int64 `db:"total_count" json:"total_count"` +} + +func (q *Queries) GetBitrixPipelinesWithPagination(ctx context.Context, arg GetBitrixPipelinesWithPaginationParams) ([]GetBitrixPipelinesWithPaginationRow, error) { + rows, err := q.db.QueryContext(ctx, getBitrixPipelinesWithPagination, arg.Accountid, arg.Column2, arg.Limit) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetBitrixPipelinesWithPaginationRow + for rows.Next() { + var i GetBitrixPipelinesWithPaginationRow + if err := rows.Scan( + &i.ID, + &i.Bitrixid, + &i.Accountid, + &i.Name, + &i.Entitytypeid, + &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 getBitrixQuizRule = `-- name: GetBitrixQuizRule :one +SELECT id, accountid, quizid, performerid, pipelineid, typeid, stageid, sourceid, statusid, fieldsrule, tagstoadd, deleted, createdat, leadflag FROM BitrixRule WHERE QuizID = $1 AND Deleted = false +` + +func (q *Queries) GetBitrixQuizRule(ctx context.Context, quizid int32) (Bitrixrule, error) { + row := q.db.QueryRowContext(ctx, getBitrixQuizRule, quizid) + var i Bitrixrule + err := row.Scan( + &i.ID, + &i.Accountid, + &i.Quizid, + &i.Performerid, + &i.Pipelineid, + &i.Typeid, + &i.Stageid, + &i.Sourceid, + &i.Statusid, + &i.Fieldsrule, + &i.Tagstoadd, + &i.Deleted, + &i.Createdat, + &i.Leadflag, + ) + return i, err +} + +const getBitrixStepsWithPagination = `-- name: GetBitrixStepsWithPagination :many +WITH user_data AS ( + SELECT BitrixID FROM BitrixAccounts WHERE BitrixAccounts.AccountID = $1 AND BitrixAccounts.Deleted = false +) +SELECT s.id, s.accountid, s.bitrixid, s.entityid, s.statusid, s.name, s.nameinit, s.color, s.pipelineid, s.deleted, s.createdat, 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 +` + +type GetBitrixStepsWithPaginationParams struct { + Accountid string `db:"accountid" json:"accountid"` + Column2 interface{} `db:"column_2" json:"column_2"` + Limit int32 `db:"limit" json:"limit"` +} + +type GetBitrixStepsWithPaginationRow 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"` + TotalCount int64 `db:"total_count" json:"total_count"` +} + +func (q *Queries) GetBitrixStepsWithPagination(ctx context.Context, arg GetBitrixStepsWithPaginationParams) ([]GetBitrixStepsWithPaginationRow, error) { + rows, err := q.db.QueryContext(ctx, getBitrixStepsWithPagination, arg.Accountid, arg.Column2, arg.Limit) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetBitrixStepsWithPaginationRow + for rows.Next() { + var i GetBitrixStepsWithPaginationRow + if err := rows.Scan( + &i.ID, + &i.Accountid, + &i.Bitrixid, + &i.Entityid, + &i.Statusid, + &i.Name, + &i.Nameinit, + &i.Color, + &i.Pipelineid, + &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 getBitrixTokenById = `-- name: GetBitrixTokenById :one +SELECT accountid, refreshtoken, accesstoken, authcode, expiration, createdat FROM BitrixTokens WHERE accountID = $1 +` + +func (q *Queries) GetBitrixTokenById(ctx context.Context, accountid string) (Bitrixtoken, error) { + row := q.db.QueryRowContext(ctx, getBitrixTokenById, accountid) + var i Bitrixtoken + err := row.Scan( + &i.Accountid, + &i.Refreshtoken, + &i.Accesstoken, + &i.Authcode, + &i.Expiration, + &i.Createdat, + ) + return i, err +} + +const getCurrentBitrixCompany = `-- name: GetCurrentBitrixCompany :one +SELECT id, accountid, bitrixid, deleted, createdat, subdomain FROM BitrixAccounts WHERE AccountID = $1 AND Deleted = false +` + +func (q *Queries) GetCurrentBitrixCompany(ctx context.Context, accountid string) (Bitrixaccount, error) { + row := q.db.QueryRowContext(ctx, getCurrentBitrixCompany, accountid) + var i Bitrixaccount + err := row.Scan( + &i.ID, + &i.Accountid, + &i.Bitrixid, + &i.Deleted, + &i.Createdat, + &i.Subdomain, + ) + return i, err +} + const getCurrentCompany = `-- name: GetCurrentCompany :one SELECT id, accountid, amoid, name, deleted, createdat, subdomain, country, driveurl FROM accountsAmo WHERE AccountID = $1 AND Deleted = false ` @@ -1632,6 +2338,46 @@ func (q *Queries) GetExistingContactAmo(ctx context.Context, arg GetExistingCont return items, nil } +const getExistingContactBitrix = `-- name: GetExistingContactBitrix :many +WITH getBitrixID AS ( + SELECT BitrixID FROM bitrixContact WHERE bitrixContact.AccountID = $1 AND bitrixContact.Field = ANY($2::text[]) +) SELECT id, accountid, bitrixid, field FROM bitrixContact +WHERE bitrixContact.AccountID = $1 AND bitrixContact.BitrixID IN (SELECT BitrixID FROM getBitrixID) +` + +type GetExistingContactBitrixParams struct { + Accountid string `db:"accountid" json:"accountid"` + Column2 []string `db:"column_2" json:"column_2"` +} + +func (q *Queries) GetExistingContactBitrix(ctx context.Context, arg GetExistingContactBitrixParams) ([]Bitrixcontact, error) { + rows, err := q.db.QueryContext(ctx, getExistingContactBitrix, arg.Accountid, pq.Array(arg.Column2)) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Bitrixcontact + for rows.Next() { + var i Bitrixcontact + if err := rows.Scan( + &i.ID, + &i.Accountid, + &i.Bitrixid, + &i.Field, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const getExpiredCountPrivilege = `-- name: GetExpiredCountPrivilege :many SELECT p.id, p.privilegeID, p.privilege_name, p.amount, p.created_at, a.user_id FROM privileges p @@ -2673,6 +3419,117 @@ func (q *Queries) GetTokenById(ctx context.Context, accountid string) (Token, er return i, err } +const getUserBitrixFieldsByID = `-- name: GetUserBitrixFieldsByID :many +SELECT id, bitrixid, accountid, entityid, fieldname, editfromlabel, fieldtype, deleted, createdat FROM BitrixFields WHERE AccountID = $1 AND Deleted = false +` + +func (q *Queries) GetUserBitrixFieldsByID(ctx context.Context, accountid string) ([]Bitrixfield, error) { + rows, err := q.db.QueryContext(ctx, getUserBitrixFieldsByID, accountid) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Bitrixfield + for rows.Next() { + var i Bitrixfield + if err := rows.Scan( + &i.ID, + &i.Bitrixid, + &i.Accountid, + &i.Entityid, + &i.Fieldname, + &i.Editfromlabel, + &i.Fieldtype, + &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 getUserBitrixPipelinesByID = `-- name: GetUserBitrixPipelinesByID :many +SELECT id, bitrixid, accountid, name, entitytypeid, deleted, createdat FROM PipelineBitrix WHERE AccountID = $1 AND Deleted = false +` + +func (q *Queries) GetUserBitrixPipelinesByID(ctx context.Context, accountid string) ([]Pipelinebitrix, error) { + rows, err := q.db.QueryContext(ctx, getUserBitrixPipelinesByID, accountid) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Pipelinebitrix + for rows.Next() { + var i Pipelinebitrix + if err := rows.Scan( + &i.ID, + &i.Bitrixid, + &i.Accountid, + &i.Name, + &i.Entitytypeid, + &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 getUserBitrixStepsByID = `-- name: GetUserBitrixStepsByID :many +SELECT id, accountid, bitrixid, entityid, statusid, name, nameinit, color, pipelineid, deleted, createdat FROM StepBitrix WHERE AccountID = $1 AND Deleted = false +` + +func (q *Queries) GetUserBitrixStepsByID(ctx context.Context, accountid string) ([]Stepbitrix, error) { + rows, err := q.db.QueryContext(ctx, getUserBitrixStepsByID, accountid) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Stepbitrix + for rows.Next() { + var i Stepbitrix + if err := rows.Scan( + &i.ID, + &i.Accountid, + &i.Bitrixid, + &i.Entityid, + &i.Statusid, + &i.Name, + &i.Nameinit, + &i.Color, + &i.Pipelineid, + &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 getUserFieldsByID = `-- name: GetUserFieldsByID :many SELECT ID,AmoID,Code,AccountID,Name,Entity,Type FROM fields @@ -2890,6 +3747,118 @@ func (q *Queries) GetUserUsersByID(ctx context.Context, amoid int32) ([]Usersamo return items, nil } +const getUserUsersByIDBitrix = `-- name: GetUserUsersByIDBitrix :many +SELECT id, accountid, bitrixiduserid, name, lastname, secondname, title, email, ufdepartment, workposition, deleted, createdat FROM BitrixAccountUsers WHERE accountID = $1 AND Deleted = false +` + +func (q *Queries) GetUserUsersByIDBitrix(ctx context.Context, accountid string) ([]Bitrixaccountuser, error) { + rows, err := q.db.QueryContext(ctx, getUserUsersByIDBitrix, accountid) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Bitrixaccountuser + for rows.Next() { + var i Bitrixaccountuser + if err := rows.Scan( + &i.ID, + &i.Accountid, + &i.Bitrixiduserid, + &i.Name, + &i.Lastname, + &i.Secondname, + &i.Title, + &i.Email, + pq.Array(&i.Ufdepartment), + &i.Workposition, + &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 getUsersBitrixWithPagination = `-- name: GetUsersBitrixWithPagination :many + +WITH user_data AS ( + SELECT BitrixID FROM BitrixAccounts WHERE BitrixAccounts.AccountID = $1 AND BitrixAccounts.Deleted = false +) +SELECT u.id, u.accountid, u.bitrixiduserid, u.name, u.lastname, u.secondname, u.title, u.email, u.ufdepartment, u.workposition, u.deleted, u.createdat, 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 +` + +type GetUsersBitrixWithPaginationParams struct { + Accountid string `db:"accountid" json:"accountid"` + Column2 interface{} `db:"column_2" json:"column_2"` + Limit int32 `db:"limit" json:"limit"` +} + +type GetUsersBitrixWithPaginationRow 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"` + TotalCount int64 `db:"total_count" json:"total_count"` +} + +// BITRIX +func (q *Queries) GetUsersBitrixWithPagination(ctx context.Context, arg GetUsersBitrixWithPaginationParams) ([]GetUsersBitrixWithPaginationRow, error) { + rows, err := q.db.QueryContext(ctx, getUsersBitrixWithPagination, arg.Accountid, arg.Column2, arg.Limit) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GetUsersBitrixWithPaginationRow + for rows.Next() { + var i GetUsersBitrixWithPaginationRow + if err := rows.Scan( + &i.ID, + &i.Accountid, + &i.Bitrixiduserid, + &i.Name, + &i.Lastname, + &i.Secondname, + &i.Title, + &i.Email, + pq.Array(&i.Ufdepartment), + &i.Workposition, + &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 getUsersWithPagination = `-- name: GetUsersWithPagination :many WITH user_data AS ( SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND accountsAmo.Deleted = false @@ -3038,6 +4007,96 @@ func (q *Queries) GettingAmoUsersTrueResults(ctx context.Context) ([]GettingAmoU return items, nil } +const gettingBitrixUsersTrueResults = `-- 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 +` + +type GettingBitrixUsersTrueResultsRow struct { + QuizID int64 `db:"quiz_id" json:"quiz_id"` + ID int64 `db:"id" json:"id"` + Result sql.NullBool `db:"result" json:"result"` + QuestionID int64 `db:"question_id" json:"question_id"` + Content sql.NullString `db:"content" json:"content"` + Session sql.NullString `db:"session" json:"session"` + Utm interface{} `db:"utm" json:"utm"` + Accesstoken string `db:"accesstoken" json:"accesstoken"` + Accountid string `db:"accountid" json:"accountid"` + Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"` + Tagstoadd json.RawMessage `db:"tagstoadd" json:"tagstoadd"` + Performerid string `db:"performerid" json:"performerid"` + Typeid string `db:"typeid" json:"typeid"` + Stageid string `db:"stageid" json:"stageid"` + Sourceid string `db:"sourceid" json:"sourceid"` + Statusid string `db:"statusid" json:"statusid"` + Pipelineid int32 `db:"pipelineid" json:"pipelineid"` + PerformerName string `db:"performer_name" json:"performer_name"` + Subdomain string `db:"subdomain" json:"subdomain"` + Accountid_2 string `db:"accountid_2" json:"accountid_2"` + Leadflag bool `db:"leadflag" json:"leadflag"` +} + +func (q *Queries) GettingBitrixUsersTrueResults(ctx context.Context) ([]GettingBitrixUsersTrueResultsRow, error) { + rows, err := q.db.QueryContext(ctx, gettingBitrixUsersTrueResults) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GettingBitrixUsersTrueResultsRow + for rows.Next() { + var i GettingBitrixUsersTrueResultsRow + if err := rows.Scan( + &i.QuizID, + &i.ID, + &i.Result, + &i.QuestionID, + &i.Content, + &i.Session, + &i.Utm, + &i.Accesstoken, + &i.Accountid, + &i.Fieldsrule, + &i.Tagstoadd, + &i.Performerid, + &i.Typeid, + &i.Stageid, + &i.Sourceid, + &i.Statusid, + &i.Pipelineid, + &i.PerformerName, + &i.Subdomain, + &i.Accountid_2, + &i.Leadflag, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const insertAnswers = `-- name: InsertAnswers :one INSERT INTO answer( content, @@ -3137,6 +4196,23 @@ func (q *Queries) InsertContactAmo(ctx context.Context, arg InsertContactAmoPara return amoid, err } +const insertContactBitrix = `-- name: InsertContactBitrix :one +INSERT INTO bitrixContact (AccountID, BitrixID, Field) VALUES ($1, $2, $3) RETURNING BitrixID +` + +type InsertContactBitrixParams struct { + Accountid string `db:"accountid" json:"accountid"` + Bitrixid int32 `db:"bitrixid" json:"bitrixid"` + Field string `db:"field" json:"field"` +} + +func (q *Queries) InsertContactBitrix(ctx context.Context, arg InsertContactBitrixParams) (int32, error) { + row := q.db.QueryRowContext(ctx, insertContactBitrix, arg.Accountid, arg.Bitrixid, arg.Field) + var bitrixid int32 + err := row.Scan(&bitrixid) + return bitrixid, err +} + const insertPrivilege = `-- name: InsertPrivilege :exec INSERT INTO privileges (privilegeID, account_id, privilege_name, amount, created_at) VALUES ($1, $2, $3, $4, $5) ` @@ -3560,6 +4636,46 @@ func (q *Queries) SearchIDByAppIDanAppHash(ctx context.Context, arg SearchIDByAp return i, err } +const setBitrixQuizSettings = `-- 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 +` + +type SetBitrixQuizSettingsParams struct { + 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"` + Leadflag bool `db:"leadflag" json:"leadflag"` + Accountid string `db:"accountid" json:"accountid"` +} + +func (q *Queries) SetBitrixQuizSettings(ctx context.Context, arg SetBitrixQuizSettingsParams) (int64, error) { + row := q.db.QueryRowContext(ctx, setBitrixQuizSettings, + arg.Quizid, + arg.Performerid, + arg.Pipelineid, + arg.Typeid, + arg.Stageid, + arg.Sourceid, + arg.Statusid, + arg.Fieldsrule, + arg.Tagstoadd, + arg.Leadflag, + arg.Accountid, + ) + var id int64 + err := row.Scan(&id) + return id, err +} + const setQuizSettings = `-- name: SetQuizSettings :one INSERT INTO rules (AccountID, QuizID, PerformerID, PipelineID, StepID, FieldsRule,TagsToAdd) SELECT u.AmoID AS AccountID,$1 AS QuizID,$2 AS PerformerID,$3 AS PipelineID, @@ -3617,6 +4733,31 @@ func (q *Queries) SettingDealAmoStatus(ctx context.Context, arg SettingDealAmoSt return err } +const settingDealBitrixStatus = `-- 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 +` + +type SettingDealBitrixStatusParams struct { + Dealid int32 `db:"dealid" json:"dealid"` + Answerid int64 `db:"answerid" json:"answerid"` + Status string `db:"status" json:"status"` + Accesstoken string `db:"accesstoken" json:"accesstoken"` +} + +func (q *Queries) SettingDealBitrixStatus(ctx context.Context, arg SettingDealBitrixStatusParams) error { + _, err := q.db.ExecContext(ctx, settingDealBitrixStatus, + arg.Dealid, + arg.Answerid, + arg.Status, + arg.Accesstoken, + ) + return err +} + const softDeleteAccount = `-- name: SoftDeleteAccount :exec WITH amoCompany AS ( SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $1 AND deleted = false @@ -3633,6 +4774,22 @@ func (q *Queries) SoftDeleteAccount(ctx context.Context, accountid string) error return err } +const softDeleteBitrixAccount = `-- 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 +` + +func (q *Queries) SoftDeleteBitrixAccount(ctx context.Context, accountid string) error { + _, err := q.db.ExecContext(ctx, softDeleteBitrixAccount, accountid) + return err +} + const softDeleteResultByID = `-- name: SoftDeleteResultByID :exec UPDATE answer SET deleted = TRUE WHERE id = $1 AND deleted = FALSE ` @@ -3743,6 +4900,130 @@ func (q *Queries) UpdateAmoContact(ctx context.Context, arg UpdateAmoContactPara return err } +const updateBitrixAccount = `-- name: UpdateBitrixAccount :exec +UPDATE BitrixAccounts SET Subdomain = $2 WHERE AccountID = $1 AND Deleted = false +` + +type UpdateBitrixAccountParams struct { + Accountid string `db:"accountid" json:"accountid"` + Subdomain string `db:"subdomain" json:"subdomain"` +} + +func (q *Queries) UpdateBitrixAccount(ctx context.Context, arg UpdateBitrixAccountParams) error { + _, err := q.db.ExecContext(ctx, updateBitrixAccount, arg.Accountid, arg.Subdomain) + return err +} + +const updateBitrixAccountUser = `-- 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 +` + +type UpdateBitrixAccountUserParams struct { + 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"` +} + +func (q *Queries) UpdateBitrixAccountUser(ctx context.Context, arg UpdateBitrixAccountUserParams) error { + _, err := q.db.ExecContext(ctx, updateBitrixAccountUser, + arg.Accountid, + arg.Bitrixiduserid, + arg.Name, + arg.Lastname, + arg.Secondname, + arg.Title, + arg.Email, + pq.Array(arg.Ufdepartment), + arg.Workposition, + ) + return err +} + +const updateBitrixContact = `-- name: UpdateBitrixContact :exec +UPDATE bitrixContact SET Field = $1,BitrixID=$3 WHERE ID = $2 +` + +type UpdateBitrixContactParams struct { + Field string `db:"field" json:"field"` + ID int64 `db:"id" json:"id"` + Bitrixid int32 `db:"bitrixid" json:"bitrixid"` +} + +func (q *Queries) UpdateBitrixContact(ctx context.Context, arg UpdateBitrixContactParams) error { + _, err := q.db.ExecContext(ctx, updateBitrixContact, arg.Field, arg.ID, arg.Bitrixid) + return err +} + +const updateBitrixFieldRules = `-- 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 +` + +type UpdateBitrixFieldRulesParams struct { + Fieldsrule json.RawMessage `db:"fieldsrule" json:"fieldsrule"` + Accountid string `db:"accountid" json:"accountid"` + Quizid int32 `db:"quizid" json:"quizid"` +} + +func (q *Queries) UpdateBitrixFieldRules(ctx context.Context, arg UpdateBitrixFieldRulesParams) error { + _, err := q.db.ExecContext(ctx, updateBitrixFieldRules, arg.Fieldsrule, arg.Accountid, arg.Quizid) + return err +} + +const updateBitrixFields = `-- 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 +` + +func (q *Queries) UpdateBitrixFields(ctx context.Context, dollar_1 json.RawMessage) error { + _, err := q.db.ExecContext(ctx, updateBitrixFields, dollar_1) + return err +} + +const updateBitrixPipelines = `-- 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) +` + +func (q *Queries) UpdateBitrixPipelines(ctx context.Context, dollar_1 json.RawMessage) error { + _, err := q.db.ExecContext(ctx, updateBitrixPipelines, dollar_1) + return err +} + +const updateBitrixSteps = `-- 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) +` + +func (q *Queries) UpdateBitrixSteps(ctx context.Context, dollar_1 json.RawMessage) error { + _, err := q.db.ExecContext(ctx, updateBitrixSteps, dollar_1) + return err +} + const updateFieldRules = `-- name: UpdateFieldRules :exec UPDATE rules SET FieldsRule = $1 WHERE AccountID = (SELECT AmoID FROM accountsAmo WHERE accountsAmo.AccountID = $2 AND accountsAmo.Deleted = false) AND QuizID = $3 AND Deleted = false @@ -3910,6 +5191,45 @@ func (q *Queries) UpdatingDealAmoStatus(ctx context.Context, arg UpdatingDealAmo return err } +const webhookBitrixDelete = `-- 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) +` + +func (q *Queries) WebhookBitrixDelete(ctx context.Context, bitrixid string) error { + _, err := q.db.ExecContext(ctx, webhookBitrixDelete, bitrixid) + return err +} + +const webhookBitrixUpdate = `-- 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 +` + +type WebhookBitrixUpdateParams struct { + Accesstoken string `db:"accesstoken" json:"accesstoken"` + Refreshtoken string `db:"refreshtoken" json:"refreshtoken"` + Column3 int64 `db:"column_3" json:"column_3"` + Column4 int64 `db:"column_4" json:"column_4"` + Accountid string `db:"accountid" json:"accountid"` +} + +func (q *Queries) WebhookBitrixUpdate(ctx context.Context, arg WebhookBitrixUpdateParams) error { + _, err := q.db.ExecContext(ctx, webhookBitrixUpdate, + arg.Accesstoken, + arg.Refreshtoken, + arg.Column3, + arg.Column4, + arg.Accountid, + ) + return err +} + const webhookDelete = `-- name: WebhookDelete :exec WITH companyDel AS ( UPDATE accountsAmo SET Deleted = true WHERE accountsAmo.AmoID = $1 RETURNING AccountID diff --git a/model/bitrix.go b/model/bitrix.go new file mode 100644 index 0000000..05bdfdf --- /dev/null +++ b/model/bitrix.go @@ -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 // значение поля +} diff --git a/model/bitrixResp.go b/model/bitrixResp.go new file mode 100644 index 0000000..94450c4 --- /dev/null +++ b/model/bitrixResp.go @@ -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"` +} diff --git a/model/bitrixTypes.go b/model/bitrixTypes.go new file mode 100644 index 0000000..3471e8b --- /dev/null +++ b/model/bitrixTypes.go @@ -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" +) diff --git a/repository/bitrix/bitrix.go b/repository/bitrix/bitrix.go new file mode 100644 index 0000000..923eab4 --- /dev/null +++ b/repository/bitrix/bitrix.go @@ -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 +}