package crm import ( "jannex/admin-dashboard-backend/modules/config" "jannex/admin-dashboard-backend/modules/database" "jannex/admin-dashboard-backend/modules/logger" "jannex/admin-dashboard-backend/modules/notification" "jannex/admin-dashboard-backend/modules/structs" "jannex/admin-dashboard-backend/modules/utils" "jannex/admin-dashboard-backend/socketclients" "sort" "time" "git.ex.umbach.dev/Alex/roese-utils/rslogger" "github.com/go-sql-driver/mysql" "github.com/gofiber/fiber/v2" "github.com/google/uuid" "gorm.io/gorm" ) func GetAllCustomers(c *fiber.Ctx) error { // swagger:operation GET /crm/customers crm crmGetAllCustomers // --- // summary: Get all crm customers // produces: // - application/json // responses: // '200': // description: Crm customers // schema: // "$ref": "#/definitions/CrmTableCustomer" // '401': // description: No permissions // '500': // description: Failed to get crm customers var customers []structs.CrmTableCustomer database.DB.Find(&customers) sort.Slice(customers, func(i, j int) bool { return customers[i].CreatedAt.After(customers[j].CreatedAt) }) return c.JSON(customers) } /* func GetCrmTypeCustomers(c *fiber.Ctx) error { var params structs.CrmTypeCustomerRequest if err := c.ParamsParser(¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } if !socketclients.HasPermission(c.Locals("userId").(string), utils.PermissionCrmCustomersView) { return c.SendStatus(fiber.StatusUnauthorized) } var query rspagination.PageQuery if err := c.QueryParser(&query); err != nil { return c.SendStatus(fiber.StatusBadRequest) } if params.Type == utils.CrmPipelineCustomers { return c.JSON(structs.CrmTableCustomerResponse{ Customers: crm.GetTableCustomers(params, query), TotalPages: rspagination.GetTotalPages(database.DB, utils.CrmCustomersPaginationLimit, []structs.CrmCustomer{}, nil), }) } // Check if deal phase is set if params.DealPhase == 0 { return c.SendStatus(fiber.StatusUnprocessableEntity) } if params.Type == utils.CrmPipelineDmcPipeline { return c.JSON(structs.CrmTableCustomerResponse{ Customers: crm.GetTableCustomers(params, query), TotalPages: rspagination.GetTotalPages(database.DB, utils.CrmCustomersPaginationLimit, []structs.CrmCustomer{}, structs.CrmCustomer{ Pipeline: utils.CrmPipelineDmcPipelineInt, DealPhase: params.DealPhase}), }) } if params.Type == utils.CrmPipelineSetterCloser { return c.JSON(structs.CrmTableCustomerResponse{ Customers: crm.GetTableCustomers(params, query), TotalPages: rspagination.GetTotalPages(database.DB, utils.CrmCustomersPaginationLimit, []structs.CrmCustomer{}, structs.CrmCustomer{ Pipeline: utils.CrmPipelineSetterCloserInt, DealPhase: params.DealPhase}), }) } return c.SendStatus(fiber.StatusNotFound) } */ // find customer by provided filters in body - used by groupTasks python scripts func GetCrmCustomer(c *fiber.Ctx) error { // swagger:operation POST /crm/customer crm crmGetCrmCustomer // --- // summary: Get crm customer by filters // produces: // - application/json // parameters: // - name: crmCustomer // in: body // description: Crm customer // schema: // "$ref": "#/definitions/CrmCustomer" // responses: // '200': // description: Crm customer // schema: // "$ref": "#/definitions/CrmTableCustomer" // '400': // description: Invalid request query // '401': // description: No permissions // '500': // description: Failed to get crm customer var body structs.CrmCustomer if err := c.BodyParser(&body); err != nil { return c.SendStatus(fiber.StatusBadRequest) } if !socketclients.HasPermission(c.Locals("userId").(string), utils.PermissionCrmCustomersView) { return c.SendStatus(fiber.StatusUnauthorized) } var customers []structs.CrmTableCustomer database.DB.Find(&customers, body) sort.Slice(customers, func(i, j int) bool { return customers[i].CreatedAt.After(customers[j].CreatedAt) }) return c.JSON(customers) } func GetCrmCustomerById(c *fiber.Ctx) error { // swagger:operation GET /crm/customer/view/{id} crm crmGetCrmCustomerById // --- // summary: Get crm customer by id // produces: // - application/json // parameters: // - name: id // in: path // description: Customer id // responses: // '200': // description: Crm customer // schema: // "$ref": "#/definitions/CrmCustomer" // '400': // description: Invalid request query // '401': // description: No permissions // '404': // description: Crm customer not found // '500': // description: Failed to get crm customer var params structs.CrmGetCustomerRequest if err := c.ParamsParser(¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } if !socketclients.HasPermission(c.Locals("userId").(string), utils.PermissionCrmCustomersView) { return c.SendStatus(fiber.StatusUnauthorized) } var customerResponse structs.CrmGetCustomerResponse database.DB.First(&customerResponse.Customer, "id = ?", params.Id) if customerResponse.Customer.Id != params.Id { return c.SendStatus(fiber.StatusNotFound) } // get call protocols database.DB.Find(&customerResponse.CallProtocols, "customer_id = ?", params.Id) // get links database.DB.Find(&customerResponse.Links, "customer_id = ?", params.Id) // get links history by looping through links for _, link := range customerResponse.Links { var linkHistory []structs.CrmLinkHistory database.DB.Find(&linkHistory, "link_id = ?", link.Id) customerResponse.LinkHistory = append(customerResponse.LinkHistory, linkHistory...) } return c.JSON(customerResponse) } func UpdateCrmCustomer(c *fiber.Ctx) error { // swagger:operation POST /crm/customer/update/{id} crm crmUpdateCrmCustomer // --- // summary: Update crm customer // produces: // - application/json // parameters: // - name: id // in: path // description: Customer id // - name: crmCustomer // in: body // description: Crm customer // schema: // "$ref": "#/definitions/CrmCustomer" // responses: // '200': // description: Crm customer // schema: // "$ref": "#/definitions/CrmCustomer" // '400': // description: Invalid request query // '401': // description: No permissions // '404': // description: Crm customer not found // '409': // description: Crm customer with the company name already exists // '500': // description: Failed to update crm customer var params structs.CrmGetCustomerRequest if err := c.ParamsParser(¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } if !socketclients.HasPermission(c.Locals("userId").(string), utils.PermissionCrmCustomersEdit) { return c.SendStatus(fiber.StatusUnauthorized) } var customer structs.CrmCustomer database.DB.First(&customer, "id = ?", params.Id) if customer.Id != params.Id { return c.SendStatus(fiber.StatusNotFound) } var crmCustomer map[string]interface{} if err := c.BodyParser(&crmCustomer); err != nil { return c.SendStatus(fiber.StatusBadRequest) } crmCustomer["UpdatedAt"] = time.Now() result := database.DB.Model(&structs.CrmCustomer{}). Where("id = ?", params.Id). Select("*"). // update all fields (even if they are empty) Updates(crmCustomer) if err := handleError(result, c); err != nil { return err } crmCustomer["Id"] = params.Id socketclients.BroadcastMessageToTopicStartsWith(utils.SubscribedTopicCrm, structs.SendSocketMessage{ Cmd: utils.SentCmdCrmCustomerUpdated, Body: crmCustomer, }) logger.AddCrmLog(rslogger.LogTypeInfo, "Crm customer id: %s updated with following changes: %v", params.Id, customer) return c.JSON(crmCustomer) } func CreateCrmCustomer(c *fiber.Ctx) error { // swagger:operation POST /crm/customer/create crm crmCreateCrmCustomer // --- // summary: Create crm customer // produces: // - application/json // parameters: // - name: crmCustomer // in: body // description: Crm customer // schema: // "$ref": "#/definitions/CrmCustomer" // responses: // '200': // description: Crm customer // schema: // "$ref": "#/definitions/CrmCustomer" // '400': // description: Invalid request query // '401': // description: No permissions // '409': // description: Crm customer with the company name already exists // '500': // description: Failed to create crm customer if !socketclients.HasPermission(c.Locals("userId").(string), utils.PermissionCrmCustomersCreate) { return c.SendStatus(fiber.StatusUnauthorized) } var crmCustomer map[string]interface{} if err := c.BodyParser(&crmCustomer); err != nil { return c.SendStatus(fiber.StatusBadRequest) } crmCustomer["Id"] = uuid.New().String() if crmCustomer["Pipeline"] == nil { crmCustomer["Pipeline"] = 1 } if crmCustomer["DealPhase"] == nil { crmCustomer["DealPhase"] = 1 } crmCustomer["CreatedBy"] = c.Locals("userId").(string) crmCustomer["CreatedAt"] = time.Now() // check if company name already exists var count int64 database.DB.Model(&structs.CrmCustomer{}).Where("company = ?", crmCustomer["Company"]).Count(&count) if count > 0 { logger.AddCrmLog(rslogger.LogTypeError, "Failed to create crm customer as company name already exists: %v", crmCustomer) return c.SendStatus(fiber.StatusConflict) } result := database.DB.Model(&structs.CrmCustomer{}).Create(&crmCustomer) // TODO: thats not working correctly if err := handleError(result, c); err != nil { return err } socketclients.BroadcastMessageToTopicStartsWith(utils.SubscribedTopicCrm, structs.SendSocketMessage{ Cmd: utils.SentCmdCrmCustomerCreated, Body: crmCustomer, }) logger.AddCrmLog(rslogger.LogTypeInfo, "Crm customer id: %s created with following changes: %v", crmCustomer["Id"], crmCustomer) return c.JSON(crmCustomer) } func handleError(result *gorm.DB, c *fiber.Ctx) error { if result.Error != nil { if mysqlErr, ok := result.Error.(*mysql.MySQLError); ok { switch mysqlErr.Number { case 1062: logger.AddCrmLog(rslogger.LogTypeError, "Failed to create crm customer as company name already exists: %v", result.Error.Error()) return c.SendStatus(fiber.StatusConflict) default: logger.AddCrmLog(rslogger.LogTypeError, "Failed to create crm customer: %v", result.Error.Error()) return c.SendStatus(fiber.StatusInternalServerError) } } logger.AddCrmLog(rslogger.LogTypeError, "Failed to create crm customer: %v", result.Error.Error()) return c.SendStatus(fiber.StatusInternalServerError) } return nil } func DeleteCrmCustomer(c *fiber.Ctx) error { // swagger:operation DELETE /crm/customer/delete/{id} crm crmDeleteCrmCustomer // --- // summary: Delete crm customer // produces: // - application/json // parameters: // - name: id // in: path // description: Customer id // responses: // '200': // description: Crm customer deleted // '400': // description: Invalid request query // '401': // description: No permissions // '404': // description: Crm customer not found // '500': // description: Failed to delete crm customer if !socketclients.HasPermission(c.Locals("userId").(string), utils.PermissionCrmCustomersDelete) { return c.SendStatus(fiber.StatusUnauthorized) } var params structs.CrmGetCustomerRequest if err := c.ParamsParser(¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } // check if customer exists var customer structs.CrmCustomer database.DB.First(&customer, "id = ?", params.Id) if customer.Id != params.Id { return c.SendStatus(fiber.StatusNotFound) } // delete customer result := database.DB.Delete(&customer, "id = ?", params.Id) logger.AddCrmLog(rslogger.LogTypeInfo, "Crm customer id: %s deleted: %v by user: %s", params.Id, customer, c.Locals("userId").(string)) if result.Error != nil { return c.SendStatus(fiber.StatusInternalServerError) } // delete all call protocols result = database.DB.Delete(&structs.CrmCallProtocol{}, "customer_id = ?", params.Id) logger.AddCrmLog(rslogger.LogTypeInfo, "Crm call protocols for customer id: %s deleted: %v by user: %s", params.Id, customer, c.Locals("userId").(string)) if result.Error != nil { return c.SendStatus(fiber.StatusInternalServerError) } // we need the crmLink Id to delete the link history var crmLinks []structs.CrmLink database.DB.Find(&crmLinks, "customer_id = ?", params.Id) // delete all link history for _, link := range crmLinks { result = database.DB.Delete(&structs.CrmLinkHistory{}, "link_id = ?", link.Id) logger.AddCrmLog(rslogger.LogTypeInfo, "Crm link history for link id: %s deleted: %v by user: %s", link.Id, link, c.Locals("userId").(string)) if result.Error != nil { return c.SendStatus(fiber.StatusInternalServerError) } } // delete all links result = database.DB.Delete(&structs.CrmLink{}, "customer_id = ?", params.Id) logger.AddCrmLog(rslogger.LogTypeInfo, "Crm links for customer id: %s deleted: %v by user: %s", params.Id, customer, c.Locals("userId").(string)) if result.Error != nil { return c.SendStatus(fiber.StatusInternalServerError) } socketclients.BroadcastMessageToTopicStartsWith(utils.SubscribedTopicCrm, structs.SendSocketMessage{ Cmd: utils.SentCmdCrmCustomerDeleted, Body: params.Id, }) logger.AddCrmLog(rslogger.LogTypeInfo, "Crm customer id: %s deleted: %v by user: %s", params.Id, customer, c.Locals("userId").(string)) return c.SendStatus(fiber.StatusOK) } func CreateCrmCallProtocol(c *fiber.Ctx) error { // swagger:operation POST /crm/calls/create crm crmCreateCrmCallProtocol // --- // summary: Create crm call protocol // produces: // - application/json // parameters: // - name: crmCallProtocol // in: body // description: Crm call protocol // schema: // "$ref": "#/definitions/CrmCallProtocolRequest" // responses: // '200': // description: Crm call protocol created // '400': // description: Invalid request query // '401': // description: No permissions // '404': // description: Customer not found // '500': // description: Failed to create crm call protocol if !socketclients.HasPermission(c.Locals("userId").(string), utils.PermissionCrmCallProtocolCreate) { return c.SendStatus(fiber.StatusUnauthorized) } var body structs.CrmCallProtocolRequest if err := c.BodyParser(&body); err != nil { return c.SendStatus(fiber.StatusBadRequest) } // check if customer exists var count int64 database.DB.Model(&structs.CrmCustomer{}).Where("id = ?", body.CustomerId).Count(&count) if count == 0 { logger.AddCrmLog(rslogger.LogTypeError, "Failed to create crm call protocol as customer id not found: %v", body.CustomerId) return c.SendStatus(fiber.StatusNotFound) } // create crm call protocol var crmCallProtocol structs.CrmCallProtocol crmCallProtocol.Id = uuid.New().String() crmCallProtocol.CustomerId = body.CustomerId crmCallProtocol.CallType = body.CallType crmCallProtocol.CalledAt = body.CalledAt crmCallProtocol.Telephone = body.Telephone crmCallProtocol.Notes = body.Notes crmCallProtocol.ResultReached = body.ResultReached crmCallProtocol.ResultWhoPickedUp = body.ResultWhoPickedUp crmCallProtocol.ResultExpressedInterest = body.ResultExpressedInterest crmCallProtocol.ResultScheduled = body.ResultScheduled crmCallProtocol.CreatedBy = c.Locals("userId").(string) crmCallProtocol.CreatedAt = time.Now() result := database.DB.Model(&structs.CrmCallProtocol{}).Create(&crmCallProtocol) if result.Error != nil { logger.AddCrmLog(rslogger.LogTypeError, "Failed to create crm call protocol: %v", result.Error.Error()) return c.SendStatus(fiber.StatusInternalServerError) } // update last contact date result = database.DB.Model(&structs.CrmCustomer{}). Where("id = ?", body.CustomerId). Update("last_contact", time.Now()) if result.Error != nil { logger.AddCrmLog(rslogger.LogTypeError, "Failed to update last contact date: %v", result.Error.Error()) return c.SendStatus(fiber.StatusInternalServerError) } socketclients.BroadcastMessageToTopicStartsWith(utils.SubscribedTopicCrm, structs.SendSocketMessage{ Cmd: utils.SentCmdCrmCallProtocolCreated, Body: struct { CallProtocol structs.CrmCallProtocol Customer struct { Id string LastContact time.Time } }{ CallProtocol: crmCallProtocol, Customer: struct { Id string LastContact time.Time }{ Id: body.CustomerId, LastContact: time.Now(), }, }, }) logger.AddCrmLog(rslogger.LogTypeInfo, "Crm call protocol id: %s created: %v", crmCallProtocol.Id, crmCallProtocol) return c.SendStatus(fiber.StatusOK) } func GetCrmCallProtocols(c *fiber.Ctx) error { // swagger:operation GET /crm/calls/{customerId} crm crmGetCrmCallProtocols // --- // summary: Get crm call protocols // produces: // - application/json // parameters: // - name: customerId // in: path // description: Customer id // responses: // '200': // description: Crm call protocols // schema: // "$ref": "#/definitions/CrmCallProtocol" // '400': // description: Invalid request query // '401': // description: No permissions // '500': // description: Failed to get crm call protocols if !socketclients.HasPermission(c.Locals("userId").(string), utils.PermissionCrmCallProtocolView) { return c.SendStatus(fiber.StatusUnauthorized) } var params structs.CrmGetCustomerRequest if err := c.ParamsParser(¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } var crmCallProtocols []structs.CrmCallProtocol database.DB.Find(&crmCallProtocols, "customer_id = ?", params.Id) return c.JSON(crmCallProtocols) } func DeleteCrmCallProtocol(c *fiber.Ctx) error { // swagger:operation DELETE /crm/calls/delete/{id} crm crmDeleteCrmCallProtocol // --- // summary: Delete crm call protocol // produces: // - application/json // parameters: // - name: id // in: path // description: Call protocol id // responses: // '200': // description: Crm call protocol deleted // '400': // description: Invalid request query // '401': // description: No permissions // '404': // description: Crm call protocol not found // '500': // description: Failed to delete crm call protocol if !socketclients.HasPermission(c.Locals("userId").(string), utils.PermissionCrmCallProtocolDelete) { return c.SendStatus(fiber.StatusUnauthorized) } var params structs.CrmGetCustomerRequest if err := c.ParamsParser(¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } var crmCallProtocol structs.CrmCallProtocol database.DB.First(&crmCallProtocol, "id = ?", params.Id) if crmCallProtocol.Id != params.Id { return c.SendStatus(fiber.StatusNotFound) } result := database.DB.Delete(&crmCallProtocol, "id = ?", params.Id) if result.Error != nil { return c.SendStatus(fiber.StatusInternalServerError) } socketclients.BroadcastMessageToTopicStartsWith(utils.SubscribedTopicCrm, structs.SendSocketMessage{ Cmd: utils.SentCmdCrmCallProtocolDeleted, Body: struct { Id string CustomerId string }{ Id: crmCallProtocol.Id, CustomerId: crmCallProtocol.CustomerId, }, }) logger.AddCrmLog(rslogger.LogTypeInfo, "Crm call protocol id: %s deleted: %v", crmCallProtocol.Id, crmCallProtocol) return c.SendStatus(fiber.StatusOK) } func CreateCrmLink(c *fiber.Ctx) error { // swagger:operation POST /crm/links crm crmCreateCrmLink // --- // summary: Create crm link // produces: // - application/json // parameters: // - name: crmLink // in: body // description: Crm link // schema: // "$ref": "#/definitions/CrmLink" // responses: // '200': // description: Crm link created // '400': // description: Invalid request query // '401': // description: No permissions // '500': // description: Failed to create crm link if !socketclients.HasPermission(c.Locals("userId").(string), utils.PermissionCrmLinkCreate) { return c.SendStatus(fiber.StatusUnauthorized) } var body structs.CrmLink if err := c.BodyParser(&body); err != nil || body.CustomerId == "" || body.Name == "" || body.Url == "" { return c.SendStatus(fiber.StatusBadRequest) } // check if customer exists var count int64 database.DB.Model(&structs.CrmCustomer{}).Where("id = ?", body.CustomerId).Count(&count) if count == 0 { logger.AddCrmLog(rslogger.LogTypeError, "Failed to create crm link as customer id not found: %v", body.CustomerId) return c.SendStatus(fiber.StatusNotFound) } body.Id = uuid.New().String() body.CreatedBy = c.Locals("userId").(string) body.CreatedAt = time.Now() result := database.DB.Model(&structs.CrmLink{}).Create(&body) if result.Error != nil { logger.AddCrmLog(rslogger.LogTypeError, "Failed to create crm link: %v", result.Error.Error()) return c.SendStatus(fiber.StatusInternalServerError) } socketclients.BroadcastMessageToTopicStartsWith(utils.SubscribedTopicCrm, structs.SendSocketMessage{ Cmd: utils.SentCmdCrmLinkCreated, Body: body, }) logger.AddCrmLog(rslogger.LogTypeInfo, "Crm link id: %s created: %v", body.Id, body) return c.SendStatus(fiber.StatusOK) } func GetCrmLinks(c *fiber.Ctx) error { // swagger:operation GET /crm/links/{customerId} crm crmGetCrmLinks // --- // summary: Get crm links // produces: // - application/json // parameters: // - name: customerId // in: path // description: Customer id // responses: // '200': // description: Crm links // schema: // "$ref": "#/definitions/CrmLink" // '400': // description: Invalid request query // '401': // description: No permissions // '500': // description: Failed to get crm links if !socketclients.HasPermission(c.Locals("userId").(string), utils.PermissionCrmLinkView) { return c.SendStatus(fiber.StatusUnauthorized) } var params structs.CrmGetCustomerRequest if err := c.ParamsParser(¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } var crmLinks []structs.CrmLink database.DB.Find(&crmLinks, "customer_id = ?", params.Id) return c.JSON(crmLinks) } func CrmUseLink(c *fiber.Ctx) error { // swagger:operation POST /crm/link/{id} crm crmUseLink // --- // summary: Use crm link // produces: // - application/json // parameters: // - name: id // in: path // description: Link id // responses: // '200': // description: Crm link used // '400': // description: Invalid request query // '401': // description: No permissions // '404': // description: Crm link not found // '500': // description: Failed to use crm link var params structs.CrmGetCustomerRequest if err := c.ParamsParser(¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } var link structs.CrmLink database.DB.First(&link, "id = ?", params.Id) if link.Id != params.Id { return c.SendStatus(fiber.StatusNotFound) } // create link history linkHistory := structs.CrmLinkHistory{ LinkId: link.Id, UserAgent: string(c.Context().UserAgent()), UsedAt: time.Now(), } result := database.DB.Model(&structs.CrmLinkHistory{}).Create(&linkHistory) if result.Error != nil { logger.AddCrmLog(rslogger.LogTypeError, "Failed to use crm link: %v", result.Error.Error()) return c.SendStatus(fiber.StatusInternalServerError) } socketclients.BroadcastMessageToTopicStartsWith(utils.SubscribedTopicCrm, structs.SendSocketMessage{ Cmd: utils.SentCmdCrmLinkUsed, Body: linkHistory, }) logger.AddCrmLog(rslogger.LogTypeInfo, "Crm link id: %s used: %v", link.Id, link) // only for debugging var crmCustomer structs.CrmCustomer database.DB.First(&crmCustomer, "id = ?", link.CustomerId) notification.AddNotification(nil, structs.AddNotificationRequest{ UserIds: config.Cfg.NotificationUserIds, Type: 1, Title: "Crm link used: " + link.Name + " by crm customer: " + crmCustomer.FirstName + " " + crmCustomer.Email + " (" + link.CustomerId + ")", }) return c.Redirect(link.Url) } func DeleteCrmLink(c *fiber.Ctx) error { // swagger:operation DELETE /crm/links/{id} crm crmDeleteCrmLink // --- // summary: Delete crm link // produces: // - application/json // parameters: // - name: id // in: path // description: Link id // responses: // '200': // description: Crm link deleted // '400': // description: Invalid request query // '401': // description: No permissions // '404': // description: Crm link not found // '500': // description: Failed to delete crm link if !socketclients.HasPermission(c.Locals("userId").(string), utils.PermissionCrmLinkDelete) { return c.SendStatus(fiber.StatusUnauthorized) } var params structs.CrmGetCustomerRequest if err := c.ParamsParser(¶ms); err != nil { return c.SendStatus(fiber.StatusBadRequest) } var link structs.CrmLink database.DB.First(&link, "id = ?", params.Id) if link.Id != params.Id { return c.SendStatus(fiber.StatusNotFound) } result := database.DB.Delete(&link, "id = ?", params.Id) if result.Error != nil { logger.AddCrmLog(rslogger.LogTypeError, "Failed to delete crm link: %v", result.Error.Error()) return c.SendStatus(fiber.StatusInternalServerError) } // delete all link history result = database.DB.Delete(&structs.CrmLinkHistory{}, "link_id = ?", params.Id) if result.Error != nil { logger.AddCrmLog(rslogger.LogTypeError, "Failed to delete crm link history: %v", result.Error.Error()) return c.SendStatus(fiber.StatusInternalServerError) } socketclients.BroadcastMessageToTopicStartsWith(utils.SubscribedTopicCrm, structs.SendSocketMessage{ Cmd: utils.SentCmdCrmLinkDeleted, Body: params.Id, }) logger.AddCrmLog(rslogger.LogTypeInfo, "Crm link id: %s deleted: %v", link.Id, link) return c.SendStatus(fiber.StatusOK) } func CrmNoLinkProvidedRedirect(c *fiber.Ctx) error { // swagger:operation GET /crm/nolink crm crmNoLinkProvidedRedirect // --- // summary: Redirect to crm no link provided // produces: // - application/json // responses: // '200': // description: Redirect to crm no link provided // '500': // description: Failed to redirect to crm no link provided return c.Redirect("https://jannex.de?utm_source=web&utm_medium=web&utm_campaign=linkredirect&utm_content=redirect") }