增加个人办公模块
This commit is contained in:
@@ -0,0 +1,842 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"server/models"
|
||||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
)
|
||||
|
||||
// BackendErpContactController 通讯录管理接口
|
||||
type BackendErpContactController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
type erpContactDTO struct {
|
||||
ID uint64 `json:"id"`
|
||||
Tid uint64 `json:"tid"`
|
||||
EmployeeID uint64 `json:"employee_id"`
|
||||
OrgID uint64 `json:"org_id"`
|
||||
OrgName string `json:"org_name"`
|
||||
ContactType int8 `json:"contact_type"`
|
||||
ContactName string `json:"contact_name"`
|
||||
Gender int8 `json:"gender"`
|
||||
Phone string `json:"phone"`
|
||||
WorkPhone string `json:"work_phone"`
|
||||
Email string `json:"email"`
|
||||
Wechat string `json:"wechat"`
|
||||
Avatar string `json:"avatar"`
|
||||
CompanyName string `json:"company_name"`
|
||||
DeptName string `json:"dept_name"`
|
||||
PositionID uint64 `json:"position_id"`
|
||||
PositionTitle string `json:"position_title"`
|
||||
Address string `json:"address"`
|
||||
Remark string `json:"remark"`
|
||||
IsStarred int8 `json:"is_starred"`
|
||||
Sort uint `json:"sort"`
|
||||
Status int8 `json:"status"`
|
||||
CreateTime string `json:"create_time"`
|
||||
}
|
||||
|
||||
// List 获取通讯录列表(支持分页、搜索、按组织筛选)
|
||||
// GET /backend/erp/contact/list
|
||||
func (c *BackendErpContactController) List() {
|
||||
tid, _ := c.GetInt64("tid")
|
||||
page, _ := c.GetInt("page", 1)
|
||||
pageSize, _ := c.GetInt("page_size", 20)
|
||||
keyword := strings.TrimSpace(c.GetString("keyword"))
|
||||
orgID, _ := c.GetUint64("org_id")
|
||||
contactType, _ := c.GetInt("contact_type")
|
||||
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize < 1 || pageSize > 100 {
|
||||
pageSize = 20
|
||||
}
|
||||
|
||||
qs := models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||
Filter("delete_time__isnull", true).
|
||||
Exclude("status", 0)
|
||||
if tid > 0 {
|
||||
qs = qs.Filter("tid", tid)
|
||||
}
|
||||
if orgID > 0 {
|
||||
qs = qs.Filter("org_id", orgID)
|
||||
}
|
||||
if contactType > 0 {
|
||||
qs = qs.Filter("contact_type", contactType)
|
||||
}
|
||||
if keyword != "" {
|
||||
cond := orm.NewCondition()
|
||||
cond = cond.Or("contact_name__contains", keyword)
|
||||
cond = cond.Or("phone__contains", keyword)
|
||||
cond = cond.Or("email__contains", keyword)
|
||||
cond = cond.Or("wechat__contains", keyword)
|
||||
qs = qs.SetCond(cond)
|
||||
}
|
||||
|
||||
total, err := qs.Count()
|
||||
if err != nil {
|
||||
c.contactJsonError(500, "查询通讯录失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var rows []models.BackendErpContact
|
||||
_, err = qs.OrderBy("-is_starred", "sort", "-id").
|
||||
Limit(pageSize, (page-1)*pageSize).
|
||||
All(&rows)
|
||||
if err != nil {
|
||||
c.contactJsonError(500, "查询通讯录失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
list := make([]erpContactDTO, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
list = append(list, c.contactDTO(row))
|
||||
}
|
||||
|
||||
c.contactJsonOK(map[string]interface{}{
|
||||
"list": list,
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": pageSize,
|
||||
})
|
||||
}
|
||||
|
||||
// Detail 获取通讯录详情
|
||||
// GET /backend/erp/contact/detail/:id
|
||||
func (c *BackendErpContactController) Detail() {
|
||||
id, ok := c.contactPathUint64(":id")
|
||||
if !ok {
|
||||
c.contactJsonError(400, "无效ID")
|
||||
return
|
||||
}
|
||||
|
||||
var row models.BackendErpContact
|
||||
err := models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||
Filter("id", id).
|
||||
Filter("delete_time__isnull", true).
|
||||
One(&row)
|
||||
if err != nil {
|
||||
c.contactJsonError(404, "联系人不存在")
|
||||
return
|
||||
}
|
||||
|
||||
c.contactJsonOK(c.contactDTO(row))
|
||||
}
|
||||
|
||||
// Create 创建联系人(手动添加外部联系人)
|
||||
// POST /backend/erp/contact/create
|
||||
func (c *BackendErpContactController) Create() {
|
||||
body := c.contactParseJSONBody()
|
||||
|
||||
contactName, _ := c.contactGetStringValue(body, "contact_name", "name")
|
||||
contactName = strings.TrimSpace(contactName)
|
||||
if contactName == "" {
|
||||
c.contactJsonError(400, "联系人姓名不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
tid, _ := c.contactGetUint64Value(body, "tid", "tenant_id")
|
||||
orgID, _ := c.contactGetUint64Value(body, "org_id")
|
||||
contactType, _ := c.contactGetIntValue(body, "contact_type")
|
||||
gender, _ := c.contactGetIntValue(body, "gender")
|
||||
phone, _ := c.contactGetStringValue(body, "phone")
|
||||
workPhone, _ := c.contactGetStringValue(body, "work_phone")
|
||||
email, _ := c.contactGetStringValue(body, "email")
|
||||
wechat, _ := c.contactGetStringValue(body, "wechat")
|
||||
avatar, _ := c.contactGetStringValue(body, "avatar")
|
||||
companyName, _ := c.contactGetStringValue(body, "company_name")
|
||||
deptName, _ := c.contactGetStringValue(body, "dept_name")
|
||||
positionID, _ := c.contactGetUint64Value(body, "position_id")
|
||||
positionTitle, _ := c.contactGetStringValue(body, "position_title")
|
||||
address, _ := c.contactGetStringValue(body, "address")
|
||||
remark, _ := c.contactGetStringValue(body, "remark")
|
||||
sortVal, _ := c.contactGetUintValue(body, "sort")
|
||||
|
||||
if contactType == 0 {
|
||||
contactType = 2 // 默认外部联系人
|
||||
}
|
||||
|
||||
row := models.BackendErpContact{
|
||||
Tid: tid,
|
||||
ContactType: int8(contactType),
|
||||
ContactName: contactName,
|
||||
Gender: int8(gender),
|
||||
Phone: contactStrPtr(phone),
|
||||
WorkPhone: contactStrPtr(workPhone),
|
||||
Email: contactStrPtr(email),
|
||||
Wechat: contactStrPtr(wechat),
|
||||
Avatar: contactStrPtr(avatar),
|
||||
CompanyName: contactStrPtr(companyName),
|
||||
DeptName: contactStrPtr(deptName),
|
||||
PositionTitle: contactStrPtr(positionTitle),
|
||||
Address: contactStrPtr(address),
|
||||
Remark: contactStrPtr(remark),
|
||||
Status: 1,
|
||||
Sort: sortVal,
|
||||
}
|
||||
if orgID > 0 {
|
||||
row.OrgID = &orgID
|
||||
}
|
||||
if positionID > 0 {
|
||||
row.PositionID = &positionID
|
||||
}
|
||||
|
||||
id, err := models.Orm.Insert(&row)
|
||||
if err != nil {
|
||||
c.contactJsonError(500, "创建联系人失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.contactJsonOK(map[string]interface{}{"id": id})
|
||||
}
|
||||
|
||||
// Update 更新联系人
|
||||
// POST /backend/erp/contact/update/:id
|
||||
func (c *BackendErpContactController) Update() {
|
||||
id, ok := c.contactPathUint64(":id")
|
||||
if !ok {
|
||||
c.contactJsonError(400, "无效ID")
|
||||
return
|
||||
}
|
||||
|
||||
body := c.contactParseJSONBody()
|
||||
update := orm.Params{}
|
||||
|
||||
if v, has := c.contactGetStringValue(body, "contact_name", "name"); has {
|
||||
v = strings.TrimSpace(v)
|
||||
if v == "" {
|
||||
c.contactJsonError(400, "联系人姓名不能为空")
|
||||
return
|
||||
}
|
||||
update["contact_name"] = v
|
||||
}
|
||||
if v, has := c.contactGetUint64Value(body, "org_id"); has {
|
||||
if v == 0 {
|
||||
update["org_id"] = nil
|
||||
} else {
|
||||
update["org_id"] = v
|
||||
}
|
||||
}
|
||||
if v, has := c.contactGetIntValue(body, "contact_type"); has {
|
||||
update["contact_type"] = int8(v)
|
||||
}
|
||||
if v, has := c.contactGetIntValue(body, "gender"); has {
|
||||
update["gender"] = int8(v)
|
||||
}
|
||||
if v, has := c.contactGetStringValue(body, "phone"); has {
|
||||
update["phone"] = contactNullableString(v)
|
||||
}
|
||||
if v, has := c.contactGetStringValue(body, "work_phone"); has {
|
||||
update["work_phone"] = contactNullableString(v)
|
||||
}
|
||||
if v, has := c.contactGetStringValue(body, "email"); has {
|
||||
update["email"] = contactNullableString(v)
|
||||
}
|
||||
if v, has := c.contactGetStringValue(body, "wechat"); has {
|
||||
update["wechat"] = contactNullableString(v)
|
||||
}
|
||||
if v, has := c.contactGetStringValue(body, "avatar"); has {
|
||||
update["avatar"] = contactNullableString(v)
|
||||
}
|
||||
if v, has := c.contactGetStringValue(body, "company_name"); has {
|
||||
update["company_name"] = contactNullableString(v)
|
||||
}
|
||||
if v, has := c.contactGetStringValue(body, "dept_name"); has {
|
||||
update["dept_name"] = contactNullableString(v)
|
||||
}
|
||||
if v, has := c.contactGetUint64Value(body, "position_id"); has {
|
||||
if v == 0 {
|
||||
update["position_id"] = nil
|
||||
} else {
|
||||
update["position_id"] = v
|
||||
}
|
||||
}
|
||||
if v, has := c.contactGetStringValue(body, "position_title"); has {
|
||||
update["position_title"] = contactNullableString(v)
|
||||
}
|
||||
if v, has := c.contactGetStringValue(body, "address"); has {
|
||||
update["address"] = contactNullableString(v)
|
||||
}
|
||||
if v, has := c.contactGetStringValue(body, "remark"); has {
|
||||
update["remark"] = contactNullableString(v)
|
||||
}
|
||||
if v, has := c.contactGetIntValue(body, "is_starred"); has {
|
||||
update["is_starred"] = int8(v)
|
||||
}
|
||||
if v, has := c.contactGetUintValue(body, "sort"); has {
|
||||
update["sort"] = v
|
||||
}
|
||||
if v, has := c.contactGetIntValue(body, "status"); has {
|
||||
update["status"] = int8(v)
|
||||
}
|
||||
|
||||
if len(update) == 0 {
|
||||
c.contactJsonError(400, "无更新字段")
|
||||
return
|
||||
}
|
||||
|
||||
num, err := models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||
Filter("id", id).
|
||||
Filter("delete_time__isnull", true).
|
||||
Update(update)
|
||||
if err != nil {
|
||||
c.contactJsonError(500, "更新联系人失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
if num == 0 {
|
||||
c.contactJsonError(404, "联系人不存在")
|
||||
return
|
||||
}
|
||||
|
||||
c.contactJsonOK(nil)
|
||||
}
|
||||
|
||||
// Delete 删除联系人(软删除)
|
||||
// DELETE /backend/erp/contact/delete/:id
|
||||
func (c *BackendErpContactController) Delete() {
|
||||
id, ok := c.contactPathUint64(":id")
|
||||
if !ok {
|
||||
c.contactJsonError(400, "无效ID")
|
||||
return
|
||||
}
|
||||
|
||||
now := time.Now().Format("2006-01-02 15:04:05")
|
||||
num, err := models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||
Filter("id", id).
|
||||
Filter("delete_time__isnull", true).
|
||||
Update(orm.Params{"delete_time": now, "status": 0})
|
||||
if err != nil {
|
||||
c.contactJsonError(500, "删除联系人失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
if num == 0 {
|
||||
c.contactJsonError(404, "联系人不存在")
|
||||
return
|
||||
}
|
||||
|
||||
c.contactJsonOK(nil)
|
||||
}
|
||||
|
||||
// Star 收藏/取消收藏联系人
|
||||
// POST /backend/erp/contact/star/:id
|
||||
func (c *BackendErpContactController) Star() {
|
||||
id, ok := c.contactPathUint64(":id")
|
||||
if !ok {
|
||||
c.contactJsonError(400, "无效ID")
|
||||
return
|
||||
}
|
||||
|
||||
body := c.contactParseJSONBody()
|
||||
starred, _ := c.contactGetIntValue(body, "is_starred", "starred")
|
||||
|
||||
num, err := models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||
Filter("id", id).
|
||||
Filter("delete_time__isnull", true).
|
||||
Update(orm.Params{"is_starred": int8(starred)})
|
||||
if err != nil {
|
||||
c.contactJsonError(500, "操作失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
if num == 0 {
|
||||
c.contactJsonError(404, "联系人不存在")
|
||||
return
|
||||
}
|
||||
|
||||
c.contactJsonOK(nil)
|
||||
}
|
||||
|
||||
// SyncAllContacts 全量同步:将所有员工同步到通讯录
|
||||
// POST /backend/erp/contact/syncAll
|
||||
func (c *BackendErpContactController) SyncAllContacts() {
|
||||
tid, _ := c.GetInt64("tid")
|
||||
|
||||
qs := models.Orm.QueryTable(new(models.BackendErpEmployee)).
|
||||
Filter("delete_time__isnull", true).
|
||||
Exclude("account_status", 2)
|
||||
if tid > 0 {
|
||||
qs = qs.Filter("tid", tid)
|
||||
}
|
||||
|
||||
var employees []models.BackendErpEmployee
|
||||
_, err := qs.All(&employees)
|
||||
if err != nil {
|
||||
c.contactJsonError(500, "查询员工失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
created := 0
|
||||
updated := 0
|
||||
for _, emp := range employees {
|
||||
tidVal := uint64(0)
|
||||
if emp.Tid != nil {
|
||||
tidVal = uint64(*emp.Tid)
|
||||
}
|
||||
empID := uint64(emp.ID)
|
||||
result := syncContactFromEmployee(tidVal, empID, &emp)
|
||||
if result == "created" {
|
||||
created++
|
||||
} else if result == "updated" {
|
||||
updated++
|
||||
}
|
||||
}
|
||||
|
||||
c.contactJsonOK(map[string]interface{}{
|
||||
"total": len(employees),
|
||||
"created": created,
|
||||
"updated": updated,
|
||||
})
|
||||
}
|
||||
|
||||
// GetContactOrgTree 获取通讯录组织树(带各部门联系人数量)
|
||||
// GET /backend/erp/contact/orgTree
|
||||
func (c *BackendErpContactController) GetContactOrgTree() {
|
||||
tid, _ := c.GetInt64("tid")
|
||||
|
||||
qs := models.Orm.QueryTable(new(models.BackendErpOrganization)).
|
||||
Filter("delete_time__isnull", true).
|
||||
Exclude("status", 0)
|
||||
if tid > 0 {
|
||||
qs = qs.Filter("tid", tid)
|
||||
}
|
||||
|
||||
var orgs []models.BackendErpOrganization
|
||||
_, err := qs.OrderBy("sort", "id").All(&orgs)
|
||||
if err != nil {
|
||||
c.contactJsonError(500, "查询组织架构失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
orgContactCounts := make(map[uint64]int64)
|
||||
cqs := models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||
Filter("delete_time__isnull", true).
|
||||
Exclude("status", 0).
|
||||
Filter("contact_type", 1)
|
||||
if tid > 0 {
|
||||
cqs = cqs.Filter("tid", tid)
|
||||
}
|
||||
|
||||
type orgCount struct {
|
||||
OrgID uint64 `orm:"column(org_id)"`
|
||||
Count int64 `orm:"column(cnt)"`
|
||||
}
|
||||
var counts []orgCount
|
||||
_, err = cqs.GroupBy("org_id").All(&counts, "org_id")
|
||||
if err == nil {
|
||||
// Beego ORM GroupBy doesn't support raw count in All, so count manually
|
||||
}
|
||||
|
||||
// Fallback: count per org manually
|
||||
for _, org := range orgs {
|
||||
cnt, _ := models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||
Filter("org_id", org.ID).
|
||||
Filter("delete_time__isnull", true).
|
||||
Exclude("status", 0).
|
||||
Filter("contact_type", 1).
|
||||
Count()
|
||||
orgContactCounts[org.ID] = cnt
|
||||
}
|
||||
|
||||
// Also get total internal contacts count for root
|
||||
totalInternal, _ := cqs.Count()
|
||||
|
||||
// Build tree
|
||||
tree := c.buildContactOrgTree(orgs, orgContactCounts, uint64(totalInternal))
|
||||
|
||||
c.contactJsonOK(tree)
|
||||
}
|
||||
|
||||
// buildContactOrgTree 构建通讯录组织树
|
||||
func (c *BackendErpContactController) buildContactOrgTree(
|
||||
orgs []models.BackendErpOrganization,
|
||||
counts map[uint64]int64,
|
||||
totalInternal uint64,
|
||||
) []map[string]interface{} {
|
||||
nodeMap := make(map[uint64]map[string]interface{})
|
||||
tree := make([]map[string]interface{}, 0)
|
||||
|
||||
for _, org := range orgs {
|
||||
node := map[string]interface{}{
|
||||
"id": org.ID,
|
||||
"org_name": org.OrgName,
|
||||
"parent_id": org.ParentID,
|
||||
"is_company": org.IsCompany,
|
||||
"status": org.Status,
|
||||
"contact_count": counts[org.ID],
|
||||
"children": make([]map[string]interface{}, 0),
|
||||
}
|
||||
nodeMap[org.ID] = node
|
||||
}
|
||||
|
||||
for _, org := range orgs {
|
||||
node := nodeMap[org.ID]
|
||||
if org.ParentID == 0 {
|
||||
node["contact_count"] = int64(totalInternal)
|
||||
tree = append(tree, node)
|
||||
} else {
|
||||
if parent, exists := nodeMap[org.ParentID]; exists {
|
||||
parent["children"] = append(parent["children"].([]map[string]interface{}), node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tree
|
||||
}
|
||||
|
||||
// --- DTO builder ---
|
||||
|
||||
func (c *BackendErpContactController) contactDTO(row models.BackendErpContact) erpContactDTO {
|
||||
orgName := ""
|
||||
if row.OrgID != nil && *row.OrgID > 0 {
|
||||
var org models.BackendErpOrganization
|
||||
if err := models.Orm.QueryTable(new(models.BackendErpOrganization)).
|
||||
Filter("id", *row.OrgID).
|
||||
One(&org); err == nil {
|
||||
orgName = org.OrgName
|
||||
}
|
||||
}
|
||||
|
||||
return erpContactDTO{
|
||||
ID: row.ID,
|
||||
Tid: row.Tid,
|
||||
EmployeeID: contactDerefUint64(row.EmployeeID),
|
||||
OrgID: contactDerefUint64(row.OrgID),
|
||||
OrgName: orgName,
|
||||
ContactType: row.ContactType,
|
||||
ContactName: row.ContactName,
|
||||
Gender: row.Gender,
|
||||
Phone: contactDerefString(row.Phone),
|
||||
WorkPhone: contactDerefString(row.WorkPhone),
|
||||
Email: contactDerefString(row.Email),
|
||||
Wechat: contactDerefString(row.Wechat),
|
||||
Avatar: contactDerefString(row.Avatar),
|
||||
CompanyName: contactDerefString(row.CompanyName),
|
||||
DeptName: contactDerefString(row.DeptName),
|
||||
PositionID: contactDerefUint64(row.PositionID),
|
||||
PositionTitle: contactDerefString(row.PositionTitle),
|
||||
Address: contactDerefString(row.Address),
|
||||
Remark: contactDerefString(row.Remark),
|
||||
IsStarred: row.IsStarred,
|
||||
Sort: row.Sort,
|
||||
Status: row.Status,
|
||||
CreateTime: row.CreateTime.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
}
|
||||
|
||||
// --- Sync from Employee ---
|
||||
|
||||
// SyncContactOnEmployeeCreate 员工创建后同步到通讯录(由 ERP 控制器调用)
|
||||
func SyncContactOnEmployeeCreate(tid uint64, employeeID uint64, emp *models.BackendErpEmployee) {
|
||||
syncContactFromEmployee(tid, employeeID, emp)
|
||||
}
|
||||
|
||||
// SyncContactOnEmployeeUpdate 员工更新后同步到通讯录(由 ERP 控制器调用)
|
||||
func SyncContactOnEmployeeUpdate(employeeID uint64, update orm.Params) {
|
||||
var contact models.BackendErpContact
|
||||
err := models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||
Filter("employee_id", employeeID).
|
||||
Filter("delete_time__isnull", true).
|
||||
One(&contact)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
contactUpdate := orm.Params{}
|
||||
if v, ok := update["name"]; ok {
|
||||
contactUpdate["contact_name"] = v
|
||||
}
|
||||
if v, ok := update["phone"]; ok {
|
||||
contactUpdate["phone"] = v
|
||||
}
|
||||
if v, ok := update["email"]; ok {
|
||||
contactUpdate["email"] = v
|
||||
}
|
||||
if v, ok := update["wechat"]; ok {
|
||||
contactUpdate["wechat"] = v
|
||||
}
|
||||
if v, ok := update["gender"]; ok {
|
||||
contactUpdate["gender"] = v
|
||||
}
|
||||
if v, ok := update["department"]; ok {
|
||||
if v == nil {
|
||||
contactUpdate["org_id"] = nil
|
||||
} else {
|
||||
switch dept := v.(type) {
|
||||
case string:
|
||||
orgID, err := strconv.ParseUint(strings.TrimSpace(dept), 10, 64)
|
||||
if err == nil && orgID > 0 {
|
||||
contactUpdate["org_id"] = orgID
|
||||
} else {
|
||||
contactUpdate["org_id"] = nil
|
||||
}
|
||||
case uint64:
|
||||
if dept > 0 {
|
||||
contactUpdate["org_id"] = dept
|
||||
} else {
|
||||
contactUpdate["org_id"] = nil
|
||||
}
|
||||
case uint:
|
||||
if dept > 0 {
|
||||
contactUpdate["org_id"] = uint64(dept)
|
||||
} else {
|
||||
contactUpdate["org_id"] = nil
|
||||
}
|
||||
default:
|
||||
contactUpdate["org_id"] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
if v, ok := update["position"]; ok {
|
||||
contactUpdate["position_title"] = v
|
||||
}
|
||||
if v, ok := update["home_address"]; ok {
|
||||
contactUpdate["address"] = v
|
||||
}
|
||||
if v, ok := update["account_status"]; ok {
|
||||
if status, ok := v.(int8); ok && status == 2 {
|
||||
contactUpdate["status"] = int8(0)
|
||||
}
|
||||
}
|
||||
|
||||
if len(contactUpdate) > 0 {
|
||||
models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||
Filter("id", contact.ID).
|
||||
Update(contactUpdate)
|
||||
}
|
||||
}
|
||||
|
||||
// SyncContactOnEmployeeDelete 员工删除后同步通讯录(由 ERP 控制器调用)
|
||||
func SyncContactOnEmployeeDelete(employeeID uint64) {
|
||||
now := time.Now().Format("2006-01-02 15:04:05")
|
||||
models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||
Filter("employee_id", employeeID).
|
||||
Filter("delete_time__isnull", true).
|
||||
Update(orm.Params{"delete_time": now, "status": 0})
|
||||
}
|
||||
|
||||
// syncContactFromEmployee 内部同步函数
|
||||
func syncContactFromEmployee(tid uint64, employeeID uint64, emp *models.BackendErpEmployee) string {
|
||||
var existing models.BackendErpContact
|
||||
err := models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||
Filter("employee_id", employeeID).
|
||||
Filter("delete_time__isnull", true).
|
||||
One(&existing)
|
||||
|
||||
if err != nil {
|
||||
// Not found - create new contact
|
||||
var orgID *uint64
|
||||
if emp.Department != nil {
|
||||
if oid, err := strconv.ParseUint(strings.TrimSpace(*emp.Department), 10, 64); err == nil && oid > 0 {
|
||||
orgID = &oid
|
||||
}
|
||||
}
|
||||
|
||||
contact := models.BackendErpContact{
|
||||
Tid: tid,
|
||||
EmployeeID: &employeeID,
|
||||
OrgID: orgID,
|
||||
ContactType: 1,
|
||||
ContactName: emp.Name,
|
||||
Gender: emp.Gender,
|
||||
Phone: emp.Phone,
|
||||
Email: emp.Email,
|
||||
Wechat: emp.Wechat,
|
||||
PositionTitle: emp.Position,
|
||||
Address: emp.HomeAddress,
|
||||
Status: 1,
|
||||
}
|
||||
models.Orm.Insert(&contact)
|
||||
return "created"
|
||||
}
|
||||
|
||||
// Found - update
|
||||
update := orm.Params{
|
||||
"contact_name": emp.Name,
|
||||
"gender": emp.Gender,
|
||||
"phone": emp.Phone,
|
||||
"email": emp.Email,
|
||||
"wechat": emp.Wechat,
|
||||
"position_title": emp.Position,
|
||||
"address": emp.HomeAddress,
|
||||
}
|
||||
if emp.Department != nil {
|
||||
if oid, err := strconv.ParseUint(strings.TrimSpace(*emp.Department), 10, 64); err == nil && oid > 0 {
|
||||
update["org_id"] = oid
|
||||
} else {
|
||||
update["org_id"] = nil
|
||||
}
|
||||
} else {
|
||||
update["org_id"] = nil
|
||||
}
|
||||
|
||||
models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||
Filter("id", existing.ID).
|
||||
Update(update)
|
||||
return "updated"
|
||||
}
|
||||
|
||||
// --- Helper functions (package-level, shared with ERP controller) ---
|
||||
|
||||
func contactDerefString(v *string) string {
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
return *v
|
||||
}
|
||||
|
||||
func contactDerefUint64(v *uint64) uint64 {
|
||||
if v == nil {
|
||||
return 0
|
||||
}
|
||||
return *v
|
||||
}
|
||||
|
||||
func contactStrPtr(v string) *string {
|
||||
v = strings.TrimSpace(v)
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
return &v
|
||||
}
|
||||
|
||||
func contactNullableString(v string) interface{} {
|
||||
v = strings.TrimSpace(v)
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// --- Controller-level helpers ---
|
||||
|
||||
func (c *BackendErpContactController) contactParseJSONBody() map[string]interface{} {
|
||||
body := map[string]interface{}{}
|
||||
contentType := strings.ToLower(c.Ctx.Input.Header("Content-Type"))
|
||||
if !strings.Contains(contentType, "json") {
|
||||
return body
|
||||
}
|
||||
if len(c.Ctx.Input.RequestBody) == 0 {
|
||||
return body
|
||||
}
|
||||
_ = json.Unmarshal(c.Ctx.Input.RequestBody, &body)
|
||||
return body
|
||||
}
|
||||
|
||||
func (c *BackendErpContactController) contactGetStringValue(body map[string]interface{}, keys ...string) (string, bool) {
|
||||
for _, key := range keys {
|
||||
if v, ok := body[key]; ok {
|
||||
switch val := v.(type) {
|
||||
case string:
|
||||
return val, true
|
||||
case float64:
|
||||
return strconv.FormatFloat(val, 'f', -1, 64), true
|
||||
case bool:
|
||||
return strconv.FormatBool(val), true
|
||||
default:
|
||||
b, _ := json.Marshal(v)
|
||||
return strings.TrimSpace(strings.Trim(strings.ReplaceAll(strings.ReplaceAll(string(b), "\n", ""), "\r", ""), "\"")), true
|
||||
}
|
||||
}
|
||||
if c.Ctx.Request.Form == nil && c.Ctx.Request.PostForm == nil && c.Ctx.Request.MultipartForm == nil {
|
||||
_ = c.Ctx.Request.ParseMultipartForm(32 << 20)
|
||||
}
|
||||
if val := c.GetString(key); val != "" {
|
||||
return val, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (c *BackendErpContactController) contactGetIntValue(body map[string]interface{}, keys ...string) (int, bool) {
|
||||
for _, key := range keys {
|
||||
if v, ok := body[key]; ok {
|
||||
switch val := v.(type) {
|
||||
case float64:
|
||||
return int(val), true
|
||||
case int:
|
||||
return val, true
|
||||
case string:
|
||||
if strings.TrimSpace(val) == "" {
|
||||
return 0, true
|
||||
}
|
||||
parsed, err := strconv.Atoi(strings.TrimSpace(val))
|
||||
return parsed, err == nil
|
||||
}
|
||||
}
|
||||
if c.Ctx.Request.Form == nil && c.Ctx.Request.PostForm == nil && c.Ctx.Request.MultipartForm == nil {
|
||||
_ = c.Ctx.Request.ParseMultipartForm(32 << 20)
|
||||
}
|
||||
if val := c.GetString(key); val != "" {
|
||||
parsed, err := strconv.Atoi(strings.TrimSpace(val))
|
||||
return parsed, err == nil
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (c *BackendErpContactController) contactGetUintValue(body map[string]interface{}, keys ...string) (uint, bool) {
|
||||
v, ok := c.contactGetIntValue(body, keys...)
|
||||
if !ok || v < 0 {
|
||||
return 0, ok
|
||||
}
|
||||
return uint(v), true
|
||||
}
|
||||
|
||||
func (c *BackendErpContactController) contactGetUint64Value(body map[string]interface{}, keys ...string) (uint64, bool) {
|
||||
for _, key := range keys {
|
||||
if v, ok := body[key]; ok {
|
||||
switch val := v.(type) {
|
||||
case float64:
|
||||
if val < 0 {
|
||||
return 0, false
|
||||
}
|
||||
return uint64(val), true
|
||||
case int:
|
||||
if val < 0 {
|
||||
return 0, false
|
||||
}
|
||||
return uint64(val), true
|
||||
case string:
|
||||
if strings.TrimSpace(val) == "" {
|
||||
return 0, true
|
||||
}
|
||||
parsed, err := strconv.ParseUint(strings.TrimSpace(val), 10, 64)
|
||||
return parsed, err == nil
|
||||
}
|
||||
}
|
||||
if c.Ctx.Request.Form == nil && c.Ctx.Request.PostForm == nil && c.Ctx.Request.MultipartForm == nil {
|
||||
_ = c.Ctx.Request.ParseMultipartForm(32 << 20)
|
||||
}
|
||||
if val := c.GetString(key); val != "" {
|
||||
parsed, err := strconv.ParseUint(strings.TrimSpace(val), 10, 64)
|
||||
return parsed, err == nil
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (c *BackendErpContactController) contactPathUint64(name string) (uint64, bool) {
|
||||
id, err := strconv.ParseUint(c.Ctx.Input.Param(name), 10, 64)
|
||||
return id, err == nil && id > 0
|
||||
}
|
||||
|
||||
func (c *BackendErpContactController) contactJsonOK(data interface{}) {
|
||||
resp := map[string]interface{}{"code": 200, "msg": "success"}
|
||||
if data != nil {
|
||||
resp["data"] = data
|
||||
}
|
||||
c.Data["json"] = resp
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *BackendErpContactController) contactJsonError(code int, msg string) {
|
||||
c.Data["json"] = map[string]interface{}{"code": code, "msg": msg}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
@@ -454,6 +454,10 @@ func (c *BackendErpController) CreateEmployee() {
|
||||
return
|
||||
}
|
||||
|
||||
// 同步到通讯录
|
||||
tidUint := uint64(tid)
|
||||
SyncContactOnEmployeeCreate(tidUint, uint64(id), &row)
|
||||
|
||||
c.jsonOK(map[string]interface{}{"id": id})
|
||||
}
|
||||
|
||||
@@ -541,6 +545,9 @@ func (c *BackendErpController) EditEmployee() {
|
||||
return
|
||||
}
|
||||
|
||||
// 同步到通讯录
|
||||
SyncContactOnEmployeeUpdate(uint64(id), update)
|
||||
|
||||
c.jsonOK(nil)
|
||||
}
|
||||
|
||||
@@ -566,6 +573,9 @@ func (c *BackendErpController) DeleteEmployee() {
|
||||
return
|
||||
}
|
||||
|
||||
// 同步到通讯录
|
||||
SyncContactOnEmployeeDelete(uint64(id))
|
||||
|
||||
c.jsonOK(nil)
|
||||
}
|
||||
|
||||
@@ -1244,7 +1254,10 @@ func (c *BackendErpController) MoveEmployeeToOrg() {
|
||||
c.jsonError(404, "员工不存在")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// 同步到通讯录
|
||||
SyncContactOnEmployeeUpdate(uint64(employeeID), orm.Params{"department": orgID})
|
||||
|
||||
c.jsonOK(nil)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user