admin-dashboard-backend/routers/router/api/v1/crm/crm.go

527 lines
14 KiB
Go

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(&params); 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(&params); 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(&params); 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(&params); 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(&params); 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)
}