Files
gochat/internal/handler/api/v1/crm_serializer.go
T

229 lines
7.5 KiB
Go

package v1
import (
"context"
"time"
"github.com/gochat/gochat/internal/model"
"gorm.io/gorm"
)
type chatwootContactMeta struct {
Count int64 `json:"count"`
CurrentPage int `json:"current_page"`
HasMore *bool `json:"has_more,omitempty"`
}
type chatwootCompanyMeta struct {
TotalCount int64 `json:"total_count"`
Page int `json:"page"`
}
func contactListResponse(ctx context.Context, db *gorm.DB, contacts []model.Contact, total int64, page int, includeInboxes bool, hasMore *bool) map[string]any {
payload := make([]any, 0, len(contacts))
for i := range contacts {
payload = append(payload, serializeCRMContact(ctx, db, &contacts[i], includeInboxes))
}
return map[string]any{
"meta": chatwootContactMeta{Count: total, CurrentPage: page, HasMore: hasMore},
"payload": payload,
}
}
func contactPayloadResponse(ctx context.Context, db *gorm.DB, contact *model.Contact, includeInboxes bool) map[string]any {
payload := serializeCRMContact(ctx, db, contact, includeInboxes)
return map[string]any{"payload": payload}
}
func contactCreateResponse(ctx context.Context, db *gorm.DB, contact *model.Contact, contactInbox *model.ContactInbox) map[string]any {
payload := map[string]any{
"contact": serializeCRMContact(ctx, db, contact, true),
"contact_inbox": serializeContactInboxShell(contactInbox),
}
return map[string]any{"payload": payload}
}
func serializeCRMContact(ctx context.Context, db *gorm.DB, contact *model.Contact, includeInboxes bool) map[string]any {
payload := map[string]any{
"additional_attributes": jsonObject(contact.AdditionalAttributes),
"availability_status": "offline",
"email": contact.Email,
"id": contact.ID,
"name": contact.Name,
"phone_number": contact.PhoneNumber,
"blocked": contact.Blocked,
"identifier": contact.Identifier,
"thumbnail": contact.AvatarURL,
"custom_attributes": jsonObject(contact.CustomAttributes),
}
if contact.LastActivityAt != nil {
payload["last_activity_at"] = *contact.LastActivityAt
}
if !contact.CreatedAt.IsZero() {
payload["created_at"] = contact.CreatedAt.Unix()
}
if includeInboxes {
payload["contact_inboxes"] = []any{}
if db != nil {
var contactInboxes []model.ContactInbox
if err := db.WithContext(ctx).Preload("Inbox").Where("contact_id = ?", contact.ID).Order("id ASC").Find(&contactInboxes).Error; err == nil {
items := make([]any, 0, len(contactInboxes))
for i := range contactInboxes {
items = append(items, serializeContactInbox(&contactInboxes[i]))
}
payload["contact_inboxes"] = items
}
}
}
return payload
}
func serializeCompanyContact(ctx context.Context, db *gorm.DB, contact *model.Contact, currentCompanyID uint) map[string]any {
payload := serializeCRMContact(ctx, db, contact, false)
payload["company_id"] = contact.CompanyID
payload["linked_to_current_company"] = contact.CompanyID != nil && *contact.CompanyID == currentCompanyID
payload["company"] = nil
if db != nil && contact.CompanyID != nil {
var company model.Company
if err := db.WithContext(ctx).First(&company, *contact.CompanyID).Error; err == nil {
payload["company"] = serializeCompany(ctx, db, &company)
}
}
return payload
}
func serializeContactInbox(contactInbox *model.ContactInbox) map[string]any {
return map[string]any{
"source_id": contactInbox.SourceID,
"inbox": serializeInboxSlim(&contactInbox.Inbox),
}
}
func serializeContactInboxShell(contactInbox *model.ContactInbox) map[string]any {
if contactInbox == nil {
return map[string]any{"inbox": nil, "source_id": nil}
}
return map[string]any{"inbox": contactInbox.Inbox, "source_id": contactInbox.SourceID}
}
func serializeInboxSlim(inbox *model.Inbox) map[string]any {
if inbox == nil || inbox.ID == 0 {
return map[string]any{}
}
return map[string]any{
"id": inbox.ID,
"name": inbox.Name,
"channel_type": inbox.ChannelType,
"account_id": inbox.AccountID,
}
}
func companyListResponse(ctx context.Context, db *gorm.DB, companies []model.Company, total int64, page int) map[string]any {
payload := make([]any, 0, len(companies))
for i := range companies {
payload = append(payload, serializeCompany(ctx, db, &companies[i]))
}
return map[string]any{
"meta": chatwootCompanyMeta{TotalCount: total, Page: page},
"payload": payload,
}
}
func companyPayloadResponse(ctx context.Context, db *gorm.DB, company *model.Company) map[string]any {
payload := serializeCompany(ctx, db, company)
return map[string]any{"payload": payload}
}
func serializeCompany(ctx context.Context, db *gorm.DB, company *model.Company) map[string]any {
return map[string]any{
"id": company.ID,
"name": company.Name,
"contacts_count": companyContactsCount(ctx, db, company),
"domain": company.Domain,
"description": company.Description,
"custom_attributes": jsonObject(company.CustomAttributes),
"avatar_url": company.FaviconURL,
"last_activity_at": unixTimePtr(company.LastActivityAt),
"created_at": company.CreatedAt.Unix(),
"updated_at": company.UpdatedAt.Unix(),
}
}
func companyContactsResponse(ctx context.Context, db *gorm.DB, companyID uint, contacts []model.Contact, total int64, page int) map[string]any {
payload := make([]any, 0, len(contacts))
for i := range contacts {
payload = append(payload, serializeCompanyContact(ctx, db, &contacts[i], companyID))
}
return map[string]any{
"meta": chatwootCompanyMeta{TotalCount: total, Page: page},
"payload": payload,
}
}
func companyNotesResponse(ctx context.Context, db *gorm.DB, notes []model.CompanyNote, accountID uint) map[string]any {
payload := make([]any, 0, len(notes))
for i := range notes {
payload = append(payload, serializeCompanyNote(ctx, db, &notes[i], accountID))
}
return map[string]any{"payload": payload}
}
func contactNotesResponse(notes []model.Note) []any {
payload := make([]any, 0, len(notes))
for i := range notes {
payload = append(payload, serializeContactNote(&notes[i]))
}
return payload
}
func serializeContactNote(note *model.Note) map[string]any {
item := map[string]any{
"id": note.ID,
"content": note.Content,
"account_id": note.AccountID,
"contact_id": note.ContactID,
"created_at": note.CreatedAt.Unix(),
"updated_at": note.UpdatedAt.Unix(),
}
if note.UserID != nil {
item["user_id"] = *note.UserID
}
if note.User != nil && note.User.ID != 0 {
item["user"] = serializeUser(note.User, note.AccountID)
}
return item
}
func serializeCompanyNote(ctx context.Context, db *gorm.DB, note *model.CompanyNote, accountID uint) map[string]any {
item := map[string]any{
"id": note.ID,
"content": note.Content,
"company_id": note.CompanyID,
"user_id": note.UserID,
"created_at": note.CreatedAt.Unix(),
"updated_at": note.UpdatedAt.Unix(),
}
if note.User.ID != 0 {
item["user"] = serializeUser(&note.User, accountID)
} else if db != nil && note.UserID != 0 {
item["user"] = serializeUserFromDB(ctx, db, note.UserID, accountID)
}
return item
}
func companyContactsCount(ctx context.Context, db *gorm.DB, company *model.Company) int64 {
if db == nil || company == nil || company.ID == 0 {
return 0
}
var count int64
_ = db.WithContext(ctx).Model(&model.Contact{}).Where("account_id = ? AND company_id = ?", company.AccountID, company.ID).Count(&count).Error
return count
}
func unixTimePtr(value *time.Time) any {
if value == nil {
return nil
}
return value.Unix()
}