package crm import ( "fmt" "jannex/admin-dashboard-backend/modules/crm" "jannex/admin-dashboard-backend/modules/database" "jannex/admin-dashboard-backend/modules/logger" "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" "git.ex.umbach.dev/Alex/roese-utils/rspagination" "github.com/go-sql-driver/mysql" "github.com/gofiber/fiber/v2" "github.com/google/uuid" "gorm.io/gorm" ) // testing func GetAllCustomers(c *fiber.Ctx) error { 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 { // swagger:operation GET /crm/pipeline/{type}/{dealPhase} crm crmGetCrmCustomers // --- // summary: Get crm customers // produces: // - application/json // parameters: // - name: page // in: query // description: Page number // responses: // '200': // description: Crm customers // schema: // "$ref": "#/definitions/CrmTableCustomerResponse" // '400': // description: Invalid request query // '401': // description: No permissions // '404': // description: Crm type not found // '422': // description: Deal phase not set // '500': // description: Failed to get crm customers 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) } func GetCrmCustomer(c *fiber.Ctx) error { // swagger:operation GET /crm/customer/view/{id} crm crmGetCrmCustomer // --- // summary: Get crm customer // 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) 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) } 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) fmt.Println("count", count, crmCustomer["Company"]) 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 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) } socketclients.BroadcastMessageToTopicStartsWith(utils.SubscribedTopicCrm, structs.SendSocketMessage{ Cmd: utils.SentCmdCrmCallProtocolCreated, Body: crmCallProtocol, }) 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) } logger.AddCrmLog(rslogger.LogTypeInfo, "Crm call protocol id: %s delete requested", params.Id) 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) }