docxTemplater/handlers/amo.go

607 lines
15 KiB
Go
Raw Normal View History

2022-07-28 15:00:43 +00:00
package handlers
import (
"errors"
"fmt"
"github.com/Pena-Co-Ltd/amocrm_templategen_back/amo"
"github.com/Pena-Co-Ltd/amocrm_templategen_back/dal/model"
"github.com/Pena-Co-Ltd/amocrm_templategen_back/templategen"
2022-07-28 15:00:43 +00:00
"github.com/gorilla/schema"
"golang.org/x/oauth2"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"time"
)
2022-08-10 13:53:34 +00:00
type ReqAmoSaveToken struct {
2022-07-28 15:00:43 +00:00
AccessToken string `json:"access_token" schema:"access_token"`
Code string `json:"code" schema:"code"`
ClientID string `json:"client_id" schema:"client_id"`
ExpiresIn int64 `json:"expires_in" schema:"expires_in"`
TokenType string `json:"token_type" schema:"token_type"`
RefreshToken string `json:"refresh_token" schema:"refresh_token"`
State string `json:"state" schema:"state"`
FromWidget string `json:"from_widget" schema:"from_widget"`
Referer string `json:"referer" schema:"referer"`
}
func (h *Handlers) AmoSaveToken(w http.ResponseWriter, r *http.Request) {
var req ReqAmoSaveToken
2022-07-28 15:00:43 +00:00
err := r.ParseForm()
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
err = schema.NewDecoder().Decode(&req, r.Form)
2022-07-28 15:00:43 +00:00
if err != nil {
h.reportError(w, err, 500)
return
}
if req.AccessToken == "" && req.Code == "" {
2022-07-28 15:00:43 +00:00
err = errors.New("AmoErr: got empty token")
h.reportError(w, err, http.StatusBadRequest)
return
}
token := &oauth2.Token{
AccessToken: req.AccessToken,
RefreshToken: req.RefreshToken,
TokenType: req.TokenType,
Expiry: time.Now().Add(time.Duration(req.ExpiresIn) * time.Second),
2022-07-28 15:00:43 +00:00
}
amoClient, err := h.Amo.NewClient(r.Context(), req.Referer, token, req.Code)
if err != nil {
h.reportError(w, err, http.StatusForbidden)
return
2022-07-28 15:00:43 +00:00
}
token = amoClient.Token
2022-07-28 15:00:43 +00:00
user := getJwtUser(r)
if user == nil {
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
amoAcc, err := amoClient.GetAccount()
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
2022-07-28 15:00:43 +00:00
return
}
// Insert/Update token in DB
_, err = h.dal.Amo.InsertOrUpdate(r.Context(), &model.Amo{
UserID: user.UserID,
AccountID: strconv.FormatInt(amoAcc.Id, 10),
AccessToken: token.AccessToken,
RefreshToken: token.RefreshToken,
FromWidget: req.FromWidget,
Referer: req.Referer,
2022-07-28 15:00:43 +00:00
Subdomain: amoAcc.Subdomain,
ExpiresIn: token.Expiry,
TokenType: token.TokenType,
})
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
2022-07-28 15:00:43 +00:00
return
}
err = sendResponse(w, http.StatusOK, map[string]string{"accessToken": req.AccessToken})
2022-07-28 15:00:43 +00:00
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
2022-07-28 15:00:43 +00:00
}
}
func (h *Handlers) AmoWebhook(w http.ResponseWriter, r *http.Request) {
reqBody, err := ioutil.ReadAll(r.Body)
if err != nil {
h.reportError(w, err, 200)
return
}
p, err := url.ParseQuery(string(reqBody))
if err != nil {
h.reportError(w, err, 200)
return
}
leadId := p.Get("leads[status][0][id]")
subdomain := p.Get("account[subdomain]")
accId := p.Get("account[id]")
// Запрашиваем данные по аккаунту
amoData, err := h.dal.Amo.GetByAccountID(r.Context(), accId)
if err != nil {
h.reportError(w, err, 200)
return
}
amoClient, err := h.Amo.NewClient(r.Context(), subdomain, amoData.Token(), "")
2022-07-28 15:00:43 +00:00
if err != nil {
h.reportError(w, err, http.StatusForbidden)
return
}
2022-07-28 15:00:43 +00:00
lead, err := amoClient.GetLeadById(leadId)
if err != nil {
h.reportError(w, err, 200)
return
}
if lead != nil {
// fmt.Printf("Lead RESP:%+v\r\n", lead)
} else {
fmt.Println("Lead empty")
}
dataTemplate := map[string]interface{}{}
// Добавляем Инфо Лида
for k, v := range templategen.AmoLeadFieldsToRuMap(lead) {
dataTemplate[k] = v
}
//filename := fmt.Sprintf("%v", dataTemplate["Filename"])
2022-07-28 15:00:43 +00:00
// Добавялем инфо контактов
contacts := []amo.Contact{}
for _, data := range lead.Embedded.Contacts {
contact, err := amoClient.GetContactById(strconv.Itoa(data.Id))
if err == nil {
contacts = append(contacts, *contact)
} else {
fmt.Println("Something Wrong1:", err)
}
}
2022-08-10 13:53:34 +00:00
dataTemplate["Контакты"] = templategen.AmoContactsFieldsToRuMap(contacts)
2022-07-28 15:00:43 +00:00
// Добавляем инфо компаний
companies := []amo.Company{}
for _, data := range lead.Embedded.Companies {
company, err := amoClient.GetCompanyById(strconv.Itoa(data.Id))
if err == nil {
companies = append(companies, *company)
} else {
fmt.Println("Something Wrong2:", err)
}
}
2022-08-10 13:53:34 +00:00
dataTemplate["Компании"] = templategen.AmoCompaniesFieldsToRuMap(companies)
2022-07-28 15:00:43 +00:00
template, err := h.dal.Template.GetByLeadId(r.Context(), leadId)
2022-07-28 15:00:43 +00:00
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
if template == nil {
h.reportError(w, err, http.StatusNotFound)
2022-07-28 15:00:43 +00:00
return
}
switch template.StorageType {
case "gdisk":
gdiskData, err := h.dal.GDisk.GetByID(r.Context(), template.StorageID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
2022-07-28 15:00:43 +00:00
if gdiskData == nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
2022-07-28 15:00:43 +00:00
client, err := h.GDisk.NewClient(r.Context(), gdiskData.Token())
2022-07-28 15:00:43 +00:00
err = templategen.GDiskGenerateDoc(template, gdiskData.SaveFolderID, client, dataTemplate)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
case "yadisk":
yaDiskData, err := h.dal.YaDisk.GetByID(r.Context(), template.StorageID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
2022-07-28 15:00:43 +00:00
client, err := h.YaDisk.NewClient(r.Context(), yaDiskData.Token(), "")
2022-07-28 15:00:43 +00:00
err = templategen.YaDiskGenerateDoc(template, yaDiskData.SaveFolder, client, dataTemplate)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
default:
h.reportError(w, errors.New("got unknown storage"), http.StatusInternalServerError)
2022-07-28 15:00:43 +00:00
return
}
//fmt.Println("RESPONSE:", r.PostForm.Encode())
sendResponse(w, 200, nil)
}
2022-08-10 13:53:34 +00:00
type RespAmoState struct {
GenCount int `json:"gen_count"`
AuthYandexUrl string `json:"auth_yandex_url"`
AuthGoogleUrl string `json:"auth_google_url"`
Storages []interface{} `json:"storages"`
Visibility []int64 `json:"visibility"`
Creation []int64 `json:"creation"`
Delete []int64 `json:"delete"`
}
func (h *Handlers) AmoState(w http.ResponseWriter, r *http.Request) {
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, errors.New("amo account not found"), http.StatusUnauthorized)
return
2022-08-10 13:53:34 +00:00
}
yaStorages, err := h.dal.YaDisk.GetListByUserID(r.Context(), amoData.UserID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
storages := []interface{}{yaStorages}
gStorages, err := h.dal.GDisk.GetListByUserID(r.Context(), amoData.UserID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
for _, val := range gStorages {
storages = append(storages, val)
}
resp := RespAmoState{
GenCount: 97,
AuthYandexUrl: h.YaDisk.GenerateOAuthUrl(),
AuthGoogleUrl: h.GDisk.GenerateOAuthUrl(),
Storages: storages,
Visibility: amoData.AccessRules.Visibility,
Creation: amoData.AccessRules.Creation,
Delete: amoData.AccessRules.Delete,
2022-08-10 13:53:34 +00:00
}
sendResponse(w, 200, resp)
2022-08-10 13:53:34 +00:00
}
type ReqAmoGetTemplate struct {
LeadId int64 `json:"lead_id"`
TemplateId string `json:"template_id"`
}
// AmoGetTemplate - получить шаблон по LeadID или template.ID
2022-08-10 13:53:34 +00:00
func (h *Handlers) AmoGetTemplate(w http.ResponseWriter, r *http.Request) {
var req ReqAmoGetTemplate
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, errors.New("amo account not found"), http.StatusUnauthorized)
return
}
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if req.TemplateId == "" && strconv.FormatInt(req.LeadId, 10) == "" {
h.reportError(w, err, http.StatusBadRequest)
return
}
var template *model.Template
if req.TemplateId != "" {
template, err = h.dal.Template.GetByID(r.Context(), req.TemplateId)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
}
if strconv.FormatInt(req.LeadId, 10) != "" {
template, err = h.dal.Template.GetByLeadId(r.Context(), strconv.FormatInt(req.LeadId, 10))
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
}
if template == nil {
templateId, err := h.dal.Template.Insert(r.Context(), &model.Template{
UserID: amoData.UserID,
LeadId: strconv.FormatInt(req.LeadId, 10),
})
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
template = &model.Template{ID: templateId}
}
sendResponse(w, 200, template)
}
type ReqAmoSetTemplate struct {
LeadId int64 `json:"lead_id"` // Required for insert/update
TemplateId string `json:"template_id"` // Required for update - может потом удалить ?
Filename string `json:"filename"` // Required for Yandex Disk
FileID string `json:"file_id"` // Required for Google Drive
StorageID string `json:"storage_id"` // Required. id gdisk or yadisk
Storage string `json:"storage"` // Required. yadisk, gdisk - Может удалить потом?
2022-08-10 13:53:34 +00:00
}
type RespAmoSetTemplate struct {
TemplateId string `json:"template_id"`
}
// AmoSetTemplate - устанавливает/обновляет шаблон для сделки
2022-08-10 13:53:34 +00:00
func (h *Handlers) AmoSetTemplate(w http.ResponseWriter, r *http.Request) {
var req ReqAmoSetTemplate
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, errors.New("amo account not found"), http.StatusUnauthorized)
return
}
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if strconv.FormatInt(req.LeadId, 10) == "" || req.Storage == "" || req.StorageID == "" {
2022-08-10 13:53:34 +00:00
h.reportError(w, err, http.StatusBadRequest)
return
}
if req.Filename == "" && req.FileID == "" {
h.reportError(w, err, http.StatusBadRequest)
return
}
// Search/update template
var template *model.Template
update := &model.Template{
ID: req.TemplateId,
UserID: amoData.UserID,
LeadId: strconv.FormatInt(req.LeadId, 10),
Name: "Sample",
Filename: req.Filename,
StorageID: req.StorageID,
2022-08-10 13:53:34 +00:00
FileID: req.FileID,
IsDeleted: false,
}
templateId := ""
if req.TemplateId == "" {
template, err = h.dal.Template.GetByLeadId(r.Context(), strconv.FormatInt(req.LeadId, 10))
fmt.Println(0, template)
if template != nil {
err = h.dal.Template.UpdateByLeadID(r.Context(), update)
} else {
templateId, err = h.dal.Template.Insert(r.Context(), update)
}
} else {
err = h.dal.Template.UpdateByID(r.Context(), update)
}
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
sendResponse(w, 200, RespAmoSetTemplate{templateId})
}
type ReqAmoGenerateDoc struct {
LeadId int64 `json:"lead_id"`
2022-08-10 13:53:34 +00:00
}
func (h *Handlers) AmoGenerateDoc(w http.ResponseWriter, r *http.Request) {
var req ReqAmoGenerateDoc
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, errors.New("amo account not found"), http.StatusUnauthorized)
return
}
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
leadId := strconv.FormatInt(req.LeadId, 10)
if leadId == "" {
h.reportError(w, err, http.StatusBadRequest)
return
}
template, err := h.dal.Template.GetByLeadId(r.Context(), leadId)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
if template == nil {
h.reportError(w, err, http.StatusNotFound)
return
}
// Получить данные по лиду
amoClient, err := h.Amo.NewClient(r.Context(), amoData.Referer, amoData.Token(), "")
2022-08-10 13:53:34 +00:00
if err != nil {
h.reportError(w, err, http.StatusForbidden)
return
}
2022-08-10 13:53:34 +00:00
lead, err := amoClient.GetLeadById(leadId)
if err != nil {
h.reportError(w, err, 200)
return
}
if lead.Id == 0 {
fmt.Println("Lead empty")
}
dataTemplate := map[string]interface{}{}
// Добавляем Инфо Лида
for k, v := range templategen.AmoLeadFieldsToRuMap(lead) {
dataTemplate[k] = v
}
//filename := fmt.Sprintf("%v_%v_%v.docx", req.Filename, amoData.UserID, time.Now().Unix())
2022-08-10 13:53:34 +00:00
// Добавялем инфо контактов
contacts := []amo.Contact{}
for _, data := range lead.Embedded.Contacts {
contact, err := amoClient.GetContactById(strconv.Itoa(data.Id))
if err == nil {
contacts = append(contacts, *contact)
} else {
fmt.Println("Something Wrong1:", err)
}
}
dataTemplate["Контакты"] = templategen.AmoContactsFieldsToRuMap(contacts)
// Добавляем инфо компаний
companies := []amo.Company{}
for _, data := range lead.Embedded.Companies {
company, err := amoClient.GetCompanyById(strconv.Itoa(data.Id))
if err == nil {
companies = append(companies, *company)
} else {
fmt.Println("Something Wrong2:", err)
}
}
dataTemplate["Компании"] = templategen.AmoCompaniesFieldsToRuMap(companies)
switch template.StorageType {
case "gdisk":
gdiskData, err := h.dal.GDisk.GetByID(r.Context(), template.StorageID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
2022-08-10 13:53:34 +00:00
if gdiskData == nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
2022-08-10 13:53:34 +00:00
client, err := h.GDisk.NewClient(r.Context(), gdiskData.Token())
2022-08-10 13:53:34 +00:00
err = templategen.GDiskGenerateDoc(template, gdiskData.SaveFolderID, client, dataTemplate)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
case "yadisk":
yaDiskData, err := h.dal.YaDisk.GetByID(r.Context(), template.StorageID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
2022-08-10 13:53:34 +00:00
client, err := h.YaDisk.NewClient(r.Context(), yaDiskData.Token(), "")
2022-08-10 13:53:34 +00:00
err = templategen.YaDiskGenerateDoc(template, yaDiskData.SaveFolder, client, dataTemplate)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
default:
h.reportError(w, errors.New("got unknown storage"), http.StatusInternalServerError)
2022-08-10 13:53:34 +00:00
return
}
sendResponse(w, http.StatusOK, nil)
2022-08-10 13:53:34 +00:00
}
type ReqAmoAccessRules struct {
Visibility []int64 `json:"visibility"`
Creation []int64 `json:"creation"`
Delete []int64 `json:"delete"`
}
func (h *Handlers) AmoAccessRules(w http.ResponseWriter, r *http.Request) {
var req ReqAmoAccessRules
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, errors.New("amo account not found"), http.StatusUnauthorized)
return
}
isAdmin := r.Context().Value("amoIsAdmin").(bool)
if !isAdmin {
h.reportError(w, errors.New("need admin access"), http.StatusUnauthorized)
return
}
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if (req.Visibility == nil || len(req.Visibility) == 0) &&
(req.Creation == nil || len(req.Creation) == 0) &&
(req.Delete == nil || len(req.Delete) == 0) {
h.reportError(w, errors.New("empty request"), http.StatusBadRequest)
return
}
err = h.dal.Amo.UpdateAccessRules(r.Context(), amoData.ID, &model.AmoAccessRules{
Visibility: req.Visibility,
Creation: req.Creation,
Delete: req.Delete,
})
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
w.WriteHeader(200)
}