Pārlūkot izejas kodu

Merge branch 'develop' of http://code.dashoo.cn/chengjian/opms_backend into develop

Cheng Jian 3 gadi atpakaļ
vecāks
revīzija
c0200a0227
31 mainītis faili ar 865 papildinājumiem un 695 dzēšanām
  1. 1 0
      opms_admin/config/config.toml
  2. 3 3
      opms_libary/plugin/dingtalk/crypto/crypto.go
  3. 112 4
      opms_libary/plugin/dingtalk/jsapi/jsapi.go
  4. 306 5
      opms_parent/app/dao/contract/internal/ctr_contract.go
  5. 6 3
      opms_parent/app/dao/plat/internal/plat_task.go
  6. 1 1
      opms_parent/app/dao/plat/internal/plat_task_handle.go
  7. 0 459
      opms_parent/app/dao/sys/internal/sys_user.go
  8. 0 36
      opms_parent/app/dao/sys/sys_user.go
  9. 14 0
      opms_parent/app/handler/contract/ctr_contract.go
  10. 14 11
      opms_parent/app/handler/dingtalk/ding_event.go
  11. 46 0
      opms_parent/app/handler/dingtalk/ding_upload.go
  12. 16 0
      opms_parent/app/model/contract/ctr_contract.go
  13. 5 1
      opms_parent/app/model/contract/internal/ctr_contract.go
  14. 12 0
      opms_parent/app/model/dingtalk/ding_event.go
  15. 4 3
      opms_parent/app/model/plat/internal/plat_task.go
  16. 1 1
      opms_parent/app/model/plat/internal/plat_task_handle.go
  17. 4 3
      opms_parent/app/model/plat/plat_task.go
  18. 0 35
      opms_parent/app/model/sys/internal/sys_user.go
  19. 0 12
      opms_parent/app/model/sys/sys_user.go
  20. 183 25
      opms_parent/app/service/contract/ctr_contract.go
  21. 1 16
      opms_parent/app/service/contract/ctr_contract_invoice.go
  22. 19 0
      opms_parent/app/service/contract/ctr_contract_test.go
  23. 80 58
      opms_parent/app/service/cust/cust_customer.go
  24. 3 3
      opms_parent/app/service/cust/cust_customer_test.go
  25. 14 8
      opms_parent/app/service/plat/plat_task.go
  26. 4 4
      opms_parent/app/service/proj/business.go
  27. 4 3
      opms_parent/app/service/workflow/work_flow.go
  28. 1 0
      opms_parent/main.go
  29. 1 1
      opms_parent/schema/contract.sql
  30. 2 0
      opms_parent/schema/tmp.sql
  31. 8 0
      opms_parent/swaggerui/swagger.go

+ 1 - 0
opms_admin/config/config.toml

@@ -5,6 +5,7 @@
     need-advertise-addr = false
     srv-name = "dashoo.opms.admin-0.0.1"
     env = "dev"
+    websocket-addr = "127.0.0.1:8899"
 
 # 微服务注册中心配置
 [service_registry]

+ 3 - 3
opms_libary/plugin/dingtalk/crypto/crypto.go

@@ -73,7 +73,7 @@ func (c *DingTalkCrypto) GetDecryptMsg(signature, timestamp, nonce, secretMsg st
 
 func (c *DingTalkCrypto) GetEncryptMsg(msg string) (map[string]string, error) {
 	var timestamp = time.Now().UnixMilli()
-	var nonce = randomString(12)
+	var nonce = RandomString(12)
 	str, sign, err := c.GetEncryptMsgDetail(msg, fmt.Sprint(timestamp), nonce)
 
 	return map[string]string{"nonce": nonce, "timeStamp": fmt.Sprint(timestamp), "encrypt": str, "msg_signature": sign}, err
@@ -81,7 +81,7 @@ func (c *DingTalkCrypto) GetEncryptMsg(msg string) (map[string]string, error) {
 func (c *DingTalkCrypto) GetEncryptMsgDetail(msg, timestamp, nonce string) (string, string, error) {
 	size := make([]byte, 4)
 	binary.BigEndian.PutUint32(size, uint32(len(msg)))
-	msg = randomString(16) + string(size) + msg + c.SuiteKey
+	msg = RandomString(16) + string(size) + msg + c.SuiteKey
 	plantText := pkCS7Padding([]byte(msg), c.Block.BlockSize())
 	if len(plantText)%aes.BlockSize != 0 {
 		return "", "", errors.New("ERROR: 消息体size不为16的倍数")
@@ -146,7 +146,7 @@ func pkCS7Padding(ciphertext []byte, blockSize int) []byte {
 }
 
 // 随机字符串
-func randomString(n int, alphabets ...byte) string {
+func RandomString(n int, alphabets ...byte) string {
 	const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
 	var bytes = make([]byte, n)
 	var randby bool

+ 112 - 4
opms_libary/plugin/dingtalk/jsapi/jsapi.go

@@ -1,7 +1,19 @@
 package jsapi
 
-import "dashoo.cn/opms_libary/plugin/dingtalk/base"
-import "dashoo.cn/opms_libary/plugin/dingtalk/context"
+import (
+	"crypto/sha1"
+	"encoding/hex"
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	neturl "net/url"
+	"strconv"
+	"time"
+
+	"dashoo.cn/opms_libary/plugin/dingtalk/base"
+	"dashoo.cn/opms_libary/plugin/dingtalk/context"
+)
 
 //Jsapi 包装
 type Jsapi struct {
@@ -15,7 +27,103 @@ func NewJsapi(context *context.Context) *Jsapi {
 	return jsapi
 }
 
-func (s *Jsapi) Sign(jsticket, nonceStr, url string, timeStamp int64) (result string, err error) {
+func (s *Jsapi) Sign(jsTicket, nonceStr, url string, timeStamp int64) (string, error) {
+	url, err := neturl.QueryUnescape(url)
+	if err != nil {
+		return "", fmt.Errorf("decode url 异常 %s", err.Error())
+	}
+
+	plain := "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "&timestamp=" + strconv.FormatInt(timeStamp, 10)+ "&url=" + url
+	sum := sha1.Sum([]byte(plain))
+	return hex.EncodeToString(sum[:]), nil
+}
+
+func (s *Jsapi) GetJsapiTicket(accessToken string) (string, error) {
+	cacheKey := fmt.Sprintf("jsapi_ticket_%s", s.Context.AppKey)
+	val, err := s.Context.Cache.Get(cacheKey)
+	if err != nil {
+		return "", fmt.Errorf("获取 jsapi_ticket 缓存异常 %s", err.Error())
+	}
+	if val != nil {
+		return val.(string), nil
+	}
 
-	return
+	resp, err := s.GetTicketFromServer(accessToken)
+	if err != nil {
+		return "", err
+	}
+
+	err = s.Context.Cache.Set(cacheKey, resp.Ticket,
+		time.Second*time.Duration(resp.ExpiresIn-1500))
+	if err != nil {
+		return "", fmt.Errorf("设置 jsapi_ticket 缓存异常 %s", err.Error())
+	}
+	return resp.Ticket, nil
+}
+
+type JsapiTicketResp struct {
+	Errcode   int    `json:"errcode"`
+	Ticket    string `json:"ticket"`
+	Errmsg    string `json:"errmsg"`
+	ExpiresIn int    `json:"expires_in"`
 }
+
+//GetTicketFromServer 强制从服务器获取 ticket
+func (s *Jsapi) GetTicketFromServer(accessToken string) (JsapiTicketResp, error) {
+	resp := JsapiTicketResp{}
+	url := fmt.Sprintf("https://oapi.dingtalk.com/get_jsapi_ticket?access_token=%s", accessToken)
+	signResp, err := http.Get(url)
+	if err != nil {
+		return resp, fmt.Errorf("调用钉钉 get_jsapi_ticket http 请求异常 :%s", err.Error())
+	}
+	defer signResp.Body.Close()
+
+	b, err := ioutil.ReadAll(signResp.Body)
+	if err != nil {
+		return resp, fmt.Errorf("调用钉钉 get_jsapi_ticket 读取返回异常 :%s", err.Error())
+	}
+	fmt.Println(string(b))
+
+	err = json.Unmarshal(b, &resp)
+	if err != nil {
+		return resp, fmt.Errorf("调用钉钉 get_jsapi_ticket 解析 json 异常 %s:%s", string(b), err.Error())
+	}
+	if resp.Errcode != 0 {
+		return resp, fmt.Errorf("调用钉钉 get_jsapi_ticket 返回异常 %s:%s", string(b), err.Error())
+	}
+	return resp, nil
+}
+
+// type DingTokenResp struct {
+// 	Errcode     int    `json:"errcode"`
+// 	AccessToken string `json:"access_token"`
+// 	Errmsg      string `json:"errmsg"`
+// 	ExpiresIn   int    `json:"expires_in"`
+// }
+
+// func AccessToken(){
+// 	url := fmt.Sprintf(
+// 		"https://oapi.dingtalk.com/gettoken?appkey=%s&appsecret=%s",
+// 		dingtalk.Client.Context.AppKey,
+// 		dingtalk.Client.Context.AppSecret)
+// 	signResp, err := http.Get(url)
+// 	if err != nil {
+// 		return fmt.Errorf("调用钉钉 gettoken http 请求异常 :%s", err.Error())
+// 	}
+// 	defer signResp.Body.Close()
+
+// 	b, err := ioutil.ReadAll(signResp.Body)
+// 	if err != nil {
+// 		return fmt.Errorf("调用钉钉 gettoken 读取返回异常 :%s", err.Error())
+// 	}
+// 	fmt.Println(string(b))
+
+// 	tokenResp := DingTokenResp{}
+// 	err = json.Unmarshal(b, &tokenResp)
+// 	if err != nil {
+// 		return fmt.Errorf("调用钉钉 gettoken 解析 json 异常 %s:%s", string(b), err.Error())
+// 	}
+// 	if tokenResp.Errcode != 0 {
+// 		return fmt.Errorf("调用钉钉 gettoken 返回异常 %s:%s", string(b), err.Error())
+// 	}
+// }

+ 306 - 5
opms_parent/app/dao/contract/internal/ctr_contract.go

@@ -7,10 +7,13 @@ package internal
 import (
 	"context"
 	"database/sql"
+	"fmt"
+	"time"
+
 	"github.com/gogf/gf/database/gdb"
 	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/frame/gmvc"
-	"time"
+	"github.com/gogf/gf/util/gconv"
 
 	model "dashoo.cn/micro/app/model/contract"
 )
@@ -31,9 +34,13 @@ type ctrContractColumns struct {
 	ContractName      string // 合同名称
 	CustId            string // 关联客户
 	CustName          string // 客户名称
+	CustProvinceId    string // 所在省ID
+	CustProvince      string // 所在省
+	CustCityId        string // 所在市ID
+	CustCity          string // 所在市
 	NboId             string // 关联项目
 	NboName           string // 项目名称
-	ApproStatus       string // 审批状态
+	ApproStatus       string // 审核状态 10 待提交审核 20 待审核 30 审核已同意 40 审核已拒绝 50 审核已撤销
 	ContractType      string // 合同类型
 	ContractAmount    string // 合同金额
 	InvoiceAmount     string // 已开票金额
@@ -71,6 +78,10 @@ var (
 			ContractName:      "contract_name",
 			CustId:            "cust_id",
 			CustName:          "cust_name",
+			CustProvinceId:    "cust_province_id",
+			CustProvince:      "cust_province",
+			CustCityId:        "cust_city_id",
+			CustCity:          "cust_city",
 			NboId:             "nbo_id",
 			NboName:           "nbo_name",
 			ApproStatus:       "appro_status",
@@ -113,6 +124,10 @@ func NewCtrContractDao(tenant string) CtrContractDao {
 			ContractName:      "contract_name",
 			CustId:            "cust_id",
 			CustName:          "cust_name",
+			CustProvinceId:    "cust_province_id",
+			CustProvince:      "cust_province",
+			CustCityId:        "cust_city_id",
+			CustCity:          "cust_city",
 			NboId:             "nbo_id",
 			NboName:           "nbo_name",
 			ApproStatus:       "appro_status",
@@ -152,6 +167,12 @@ func (d *CtrContractDao) Ctx(ctx context.Context) *CtrContractDao {
 	return &CtrContractDao{M: d.M.Ctx(ctx)}
 }
 
+// GetCtx returns the context for current Model.
+// It returns "context.Background() i"s there's no context previously set.
+func (d *CtrContractDao) GetCtx() context.Context {
+	return d.M.GetCtx()
+}
+
 // As sets an alias name for current table.
 func (d *CtrContractDao) As(as string) *CtrContractDao {
 	return &CtrContractDao{M: d.M.As(as)}
@@ -178,6 +199,12 @@ func (d *CtrContractDao) Args(args ...interface{}) *CtrContractDao {
 	return &CtrContractDao{M: d.M.Args(args...)}
 }
 
+// Handler calls each of "handlers" on current Model and returns a new Model.
+// ModelHandler is a function that handles given Model and returns a new Model that is custom modified.
+func (d *CtrContractDao) Handler(handlers ...gdb.ModelHandler) *CtrContractDao {
+	return &CtrContractDao{M: d.M.Handler(handlers...)}
+}
+
 // LeftJoin does "LEFT JOIN ... ON ..." statement on the model.
 // The parameter <table> can be joined table and its joined condition,
 // and also with its alias name, like:
@@ -217,7 +244,33 @@ func (d *CtrContractDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *CtrCont
 	return &CtrContractDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)}
 }
 
-// Option sets the extra operation option for the model.
+// FieldCount formats and appends commonly used field "COUNT(column)" to the select fields of model.
+func (d *CtrContractDao) FieldCount(column string, as ...string) *CtrContractDao {
+	return &CtrContractDao{M: d.M.FieldCount(column, as...)}
+}
+
+// FieldSum formats and appends commonly used field "SUM(column)" to the select fields of model.
+func (d *CtrContractDao) FieldSum(column string, as ...string) *CtrContractDao {
+	return &CtrContractDao{M: d.M.FieldSum(column, as...)}
+}
+
+// FieldMin formats and appends commonly used field "MIN(column)" to the select fields of model.
+func (d *CtrContractDao) FieldMin(column string, as ...string) *CtrContractDao {
+	return &CtrContractDao{M: d.M.FieldMin(column, as...)}
+}
+
+// FieldMax formats and appends commonly used field "MAX(column)" to the select fields of model.
+func (d *CtrContractDao) FieldMax(column string, as ...string) *CtrContractDao {
+	return &CtrContractDao{M: d.M.FieldMax(column, as...)}
+}
+
+// FieldAvg formats and appends commonly used field "AVG(column)" to the select fields of model.
+func (d *CtrContractDao) FieldAvg(column string, as ...string) *CtrContractDao {
+	return &CtrContractDao{M: d.M.FieldAvg(column, as...)}
+}
+
+// Option adds extra operation option for the model.
+// Deprecated, use separate operations instead.
 func (d *CtrContractDao) Option(option int) *CtrContractDao {
 	return &CtrContractDao{M: d.M.Option(option)}
 }
@@ -228,7 +281,39 @@ func (d *CtrContractDao) OmitEmpty() *CtrContractDao {
 	return &CtrContractDao{M: d.M.OmitEmpty()}
 }
 
+// OmitEmptyWhere sets optionOmitEmptyWhere option for the model, which automatically filers
+// the Where/Having parameters for "empty" values.
+func (d *CtrContractDao) OmitEmptyWhere() *CtrContractDao {
+	return &CtrContractDao{M: d.M.OmitEmptyWhere()}
+}
+
+// OmitEmptyData sets optionOmitEmptyData option for the model, which automatically filers
+// the Data parameters for "empty" values.
+func (d *CtrContractDao) OmitEmptyData() *CtrContractDao {
+	return &CtrContractDao{M: d.M.OmitEmptyData()}
+}
+
+// OmitNil sets optionOmitNil option for the model, which automatically filers
+// the data and where parameters for "nil" values.
+func (d *CtrContractDao) OmitNil() *CtrContractDao {
+	return &CtrContractDao{M: d.M.OmitNil()}
+}
+
+// OmitNilWhere sets optionOmitNilWhere option for the model, which automatically filers
+// the Where/Having parameters for "nil" values.
+func (d *CtrContractDao) OmitNilWhere() *CtrContractDao {
+	return &CtrContractDao{M: d.M.OmitNilWhere()}
+}
+
+// OmitNilData sets optionOmitNilData option for the model, which automatically filers
+// the Data parameters for "nil" values.
+func (d *CtrContractDao) OmitNilData() *CtrContractDao {
+	return &CtrContractDao{M: d.M.OmitNilData()}
+}
+
 // Filter marks filtering the fields which does not exist in the fields of the operated table.
+// Note that this function supports only single table operations.
+// Deprecated, filter feature is automatically enabled from GoFrame v1.16.0, it is so no longer used.
 func (d *CtrContractDao) Filter() *CtrContractDao {
 	return &CtrContractDao{M: d.M.Filter()}
 }
@@ -257,18 +342,174 @@ func (d *CtrContractDao) WherePri(where interface{}, args ...interface{}) *CtrCo
 	return &CtrContractDao{M: d.M.WherePri(where, args...)}
 }
 
+// Having sets the having statement for the model.
+// The parameters of this function usage are as the same as function Where.
+// See Where.
+func (d *CtrContractDao) Having(having interface{}, args ...interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.Having(having, args...)}
+}
+
+// Wheref builds condition string using fmt.Sprintf and arguments.
+// Note that if the number of "args" is more than the place holder in "format",
+// the extra "args" will be used as the where condition arguments of the Model.
+func (d *CtrContractDao) Wheref(format string, args ...interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.Wheref(format, args...)}
+}
+
+// WhereLT builds "column < value" statement.
+func (d *CtrContractDao) WhereLT(column string, value interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereLT(column, value)}
+}
+
+// WhereLTE builds "column <= value" statement.
+func (d *CtrContractDao) WhereLTE(column string, value interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereLTE(column, value)}
+}
+
+// WhereGT builds "column > value" statement.
+func (d *CtrContractDao) WhereGT(column string, value interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereGT(column, value)}
+}
+
+// WhereGTE builds "column >= value" statement.
+func (d *CtrContractDao) WhereGTE(column string, value interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereGTE(column, value)}
+}
+
+// WhereBetween builds "column BETWEEN min AND max" statement.
+func (d *CtrContractDao) WhereBetween(column string, min, max interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereBetween(column, min, max)}
+}
+
+// WhereLike builds "column LIKE like" statement.
+func (d *CtrContractDao) WhereLike(column string, like interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereLike(column, like)}
+}
+
+// WhereIn builds "column IN (in)" statement.
+func (d *CtrContractDao) WhereIn(column string, in interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereIn(column, in)}
+}
+
+// WhereNull builds "columns[0] IS NULL AND columns[1] IS NULL ..." statement.
+func (d *CtrContractDao) WhereNull(columns ...string) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereNull(columns...)}
+}
+
+// WhereNotBetween builds "column NOT BETWEEN min AND max" statement.
+func (d *CtrContractDao) WhereNotBetween(column string, min, max interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereNotBetween(column, min, max)}
+}
+
+// WhereNotLike builds "column NOT LIKE like" statement.
+func (d *CtrContractDao) WhereNotLike(column string, like interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereNotLike(column, like)}
+}
+
+// WhereNot builds "column != value" statement.
+func (d *CtrContractDao) WhereNot(column string, value interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereNot(column, value)}
+}
+
+// WhereNotIn builds "column NOT IN (in)" statement.
+func (d *CtrContractDao) WhereNotIn(column string, in interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereNotIn(column, in)}
+}
+
+// WhereNotNull builds "columns[0] IS NOT NULL AND columns[1] IS NOT NULL ..." statement.
+func (d *CtrContractDao) WhereNotNull(columns ...string) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereNotNull(columns...)}
+}
+
+// WhereOr adds "OR" condition to the where statement.
+func (d *CtrContractDao) WhereOr(where interface{}, args ...interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOr(where, args...)}
+}
+
+// WhereOrf builds "OR" condition string using fmt.Sprintf and arguments.
+func (d *CtrContractDao) WhereOrf(format string, args ...interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOrf(format, args...)}
+}
+
+// WhereOrLT builds "column < value" statement in "OR" conditions..
+func (d *CtrContractDao) WhereOrLT(column string, value interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOrLT(column, value)}
+}
+
+// WhereOrLTE builds "column <= value" statement in "OR" conditions..
+func (d *CtrContractDao) WhereOrLTE(column string, value interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOrLTE(column, value)}
+}
+
+// WhereOrGT builds "column > value" statement in "OR" conditions..
+func (d *CtrContractDao) WhereOrGT(column string, value interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOrGT(column, value)}
+}
+
+// WhereOrGTE builds "column >= value" statement in "OR" conditions..
+func (d *CtrContractDao) WhereOrGTE(column string, value interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOrGTE(column, value)}
+}
+
+// WhereOrBetween builds "column BETWEEN min AND max" statement in "OR" conditions.
+func (d *CtrContractDao) WhereOrBetween(column string, min, max interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOrBetween(column, min, max)}
+}
+
+// WhereOrLike builds "column LIKE like" statement in "OR" conditions.
+func (d *CtrContractDao) WhereOrLike(column string, like interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOrLike(column, like)}
+}
+
+// WhereOrIn builds "column IN (in)" statement in "OR" conditions.
+func (d *CtrContractDao) WhereOrIn(column string, in interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOrIn(column, in)}
+}
+
+// WhereOrNull builds "columns[0] IS NULL OR columns[1] IS NULL ..." statement in "OR" conditions.
+func (d *CtrContractDao) WhereOrNull(columns ...string) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOrNull(columns...)}
+}
+
+// WhereOrNotBetween builds "column NOT BETWEEN min AND max" statement in "OR" conditions.
+func (d *CtrContractDao) WhereOrNotBetween(column string, min, max interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOrNotBetween(column, min, max)}
+}
+
+// WhereOrNotLike builds "column NOT LIKE like" statement in "OR" conditions.
+func (d *CtrContractDao) WhereOrNotLike(column string, like interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOrNotLike(column, like)}
+}
+
+// WhereOrNotIn builds "column NOT IN (in)" statement.
+func (d *CtrContractDao) WhereOrNotIn(column string, in interface{}) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOrNotIn(column, in)}
+}
+
+// WhereOrNotNull builds "columns[0] IS NOT NULL OR columns[1] IS NOT NULL ..." statement in "OR" conditions.
+func (d *CtrContractDao) WhereOrNotNull(columns ...string) *CtrContractDao {
+	return &CtrContractDao{M: d.M.WhereOrNotNull(columns...)}
+}
+
+// Group sets the "GROUP BY" statement for the model.
+func (d *CtrContractDao) Group(groupBy ...string) *CtrContractDao {
+	return &CtrContractDao{M: d.M.Group(groupBy...)}
+}
+
 // And adds "AND" condition to the where statement.
+// Deprecated, use Where instead.
 func (d *CtrContractDao) And(where interface{}, args ...interface{}) *CtrContractDao {
 	return &CtrContractDao{M: d.M.And(where, args...)}
 }
 
 // Or adds "OR" condition to the where statement.
+// Deprecated, use WhereOr instead.
 func (d *CtrContractDao) Or(where interface{}, args ...interface{}) *CtrContractDao {
 	return &CtrContractDao{M: d.M.Or(where, args...)}
 }
 
-// Group sets the "GROUP BY" statement for the model.
-func (d *CtrContractDao) Group(groupBy string) *CtrContractDao {
+// GroupBy sets the "GROUP BY" statement for the model.
+func (d *CtrContractDao) GroupBy(groupBy string) *CtrContractDao {
 	return &CtrContractDao{M: d.M.Group(groupBy)}
 }
 
@@ -277,6 +518,28 @@ func (d *CtrContractDao) Order(orderBy ...string) *CtrContractDao {
 	return &CtrContractDao{M: d.M.Order(orderBy...)}
 }
 
+// OrderAsc sets the "ORDER BY xxx ASC" statement for the model.
+func (d *CtrContractDao) OrderAsc(column string) *CtrContractDao {
+	return &CtrContractDao{M: d.M.OrderAsc(column)}
+}
+
+// OrderDesc sets the "ORDER BY xxx DESC" statement for the model.
+func (d *CtrContractDao) OrderDesc(column string) *CtrContractDao {
+	return &CtrContractDao{M: d.M.OrderDesc(column)}
+}
+
+// OrderRandom sets the "ORDER BY RANDOM()" statement for the model.
+func (d *CtrContractDao) OrderRandom() *CtrContractDao {
+	return &CtrContractDao{M: d.M.OrderRandom()}
+}
+
+// OrderBy is alias of Model.Order.
+// See Model.Order.
+// Deprecated, use Order instead.
+func (d *CtrContractDao) OrderBy(orderBy string) *CtrContractDao {
+	return &CtrContractDao{M: d.M.Order(orderBy)}
+}
+
 // Limit sets the "LIMIT" statement for the model.
 // The parameter <limit> can be either one or two number, if passed two number is passed,
 // it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
@@ -291,6 +554,11 @@ func (d *CtrContractDao) Offset(offset int) *CtrContractDao {
 	return &CtrContractDao{M: d.M.Offset(offset)}
 }
 
+// Distinct forces the query to only return distinct results.
+func (d *CtrContractDao) Distinct() *CtrContractDao {
+	return &CtrContractDao{M: d.M.Distinct()}
+}
+
 // Page sets the paging number for the model.
 // The parameter <page> is started from 1 for paging.
 // Note that, it differs that the Limit function start from 0 for "LIMIT" statement.
@@ -484,3 +752,36 @@ func (d *CtrContractDao) LockShared() *CtrContractDao {
 func (d *CtrContractDao) Unscoped() *CtrContractDao {
 	return &CtrContractDao{M: d.M.Unscoped()}
 }
+
+// DataScope enables the DataScope feature.
+func (d *CtrContractDao) DataScope(ctx context.Context, userCol ...string) *CtrContractDao {
+	cs := ctx.Value("contextService")
+	dataScope := gconv.Map(cs)["dataScope"].(g.Map)
+	fmt.Println(dataScope, "-----------------------")
+	fmt.Println(d.GetFieldsStr(), "---------------")
+	if dataScope != nil {
+		m := d.M
+		userIds, ok := dataScope["userIds"]
+		delete(dataScope, "userIds")
+		if ok && userIds != "-1" {
+			column := "created_by"
+			if len(userCol) == 1 {
+				column = userCol[0]
+			}
+			if d.Table == "sys_user" {
+				s := column + " IN (?) OR id IN (?)"
+				m = m.WhereOr(s, g.Slice{userIds, userIds})
+			} else {
+				m = m.WhereOr(column, userIds)
+			}
+		}
+		for k, v := range dataScope {
+			m = m.WhereOr(k, v)
+			//if ok, _ := d.M.HasField(k); ok {
+			//	m = m.WhereOr(k, v)
+			//}
+		}
+		return &CtrContractDao{M: d.M.Where(dataScope)}
+	}
+	return d
+}

+ 6 - 3
opms_parent/app/dao/plat/internal/plat_task.go

@@ -29,12 +29,13 @@ type platTaskColumns struct {
 	TaskTitle        string // 任务标题
 	TaskType         string // 任务类型
 	TaskStatus       string // 任务状态(10发起  20进行中   30流程完成)
+	Source           string // 督办事项来源
 	IsOverdue        string // 是否超期(10否20是)
-	TaskStartDate    string // 任务开始时间
-	TaskEndDate      string // 任务结束时间
+	TaskStartDate    string // 发布时间
+	TaskEndDate      string // 要求完成时间
 	TaskDesc         string // 任务说明
 	MainUserId       string // 负责人ID
-	OwnerUserId      string // 团队成员ID
+	OwnerUserId      string // 协办人ID
 	TaskLabel        string // 任务标签,号拼接
 	SupervisorUserId string // 督办人ID
 	WatchUserId      string // 监办人ID
@@ -72,6 +73,7 @@ var (
 			TaskTitle:        "task_title",
 			TaskType:         "task_type",
 			TaskStatus:       "task_status",
+			Source:           "source",
 			IsOverdue:        "is_overdue",
 			TaskStartDate:    "task_start_date",
 			TaskEndDate:      "task_end_date",
@@ -117,6 +119,7 @@ func NewPlatTaskDao(tenant string) PlatTaskDao {
 			TaskTitle:        "task_title",
 			TaskType:         "task_type",
 			TaskStatus:       "task_status",
+			Source:           "source",
 			IsOverdue:        "is_overdue",
 			TaskStartDate:    "task_start_date",
 			TaskEndDate:      "task_end_date",

+ 1 - 1
opms_parent/app/dao/plat/internal/plat_task_handle.go

@@ -30,7 +30,7 @@ type platTaskHandleColumns struct {
 	TaskStatus   string // 任务状态(10打开20关闭)
 	Step         string // 步骤号
 	MainUserId   string // 处理人ID
-	OwnerUserId  string // 团队成员ID
+	OwnerUserId  string // 协办人ID
 	HandleUserId string // 处理人ID
 	HandleDate   string // 处理时间
 	HandleStatus string // 处理结果(10接收20提交30审批通过40审批退回)

+ 0 - 459
opms_parent/app/dao/sys/internal/sys_user.go

@@ -1,459 +0,0 @@
-// ==========================================================================
-// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
-// ==========================================================================
-
-package internal
-
-import (
-	"context"
-	"database/sql"
-	"github.com/gogf/gf/database/gdb"
-	"github.com/gogf/gf/frame/g"
-	"github.com/gogf/gf/frame/gmvc"
-	"time"
-
-	model "dashoo.cn/micro/app/model/sys"
-)
-
-// SysUserDao is the manager for logic model data accessing
-// and custom defined data operations functions management.
-type SysUserDao struct {
-	gmvc.M
-	DB      gdb.DB
-	Table   string
-	Columns sysUserColumns
-}
-
-// SysUserColumns defines and stores column names for table sys_user.
-type sysUserColumns struct {
-	Id          string // 用户ID
-	DeptId      string // 部门ID
-	UserName    string // 用户账号
-	NickName    string // 用户昵称
-	UserType    string // 用户类型(00系统用户)
-	Email       string // 用户邮箱
-	Phone       string // 手机号码
-	Sex         string // 用户性别(10男20女30未知)
-	Avatar      string // 头像地址
-	Password    string // 密码
-	LoginIp     string // 最后登录IP
-	LoginDate   string // 最后登录时间
-	Remark      string // 备注
-	CreatedBy   string // 创建者
-	CreatedName string // 创建人
-	CreatedTime string // 创建时间
-	UpdatedBy   string // 更新者
-	UpdatedName string // 更新人
-	UpdatedTime string // 更新时间
-	DeletedTime string // 删除时间
-	Status      string // 帐号状态(10正常20停用)
-	UserSalt    string // 加密盐
-}
-
-var (
-	// SysUser is globally public accessible object for table sys_user operations.
-	SysUser = SysUserDao{
-		M:     g.DB("default").Model("sys_user").Safe(),
-		DB:    g.DB("default"),
-		Table: "sys_user",
-		Columns: sysUserColumns{
-			Id:          "id",
-			DeptId:      "dept_id",
-			UserName:    "user_name",
-			NickName:    "nick_name",
-			UserType:    "user_type",
-			Email:       "email",
-			Phone:       "phone",
-			Sex:         "sex",
-			Avatar:      "avatar",
-			Password:    "password",
-			LoginIp:     "login_ip",
-			LoginDate:   "login_date",
-			Remark:      "remark",
-			CreatedBy:   "created_by",
-			CreatedName: "created_name",
-			CreatedTime: "created_time",
-			UpdatedBy:   "updated_by",
-			UpdatedName: "updated_name",
-			UpdatedTime: "updated_time",
-			DeletedTime: "deleted_time",
-			Status:      "status",
-			UserSalt:    "user_salt",
-		},
-	}
-)
-
-func NewSysUserDao(tenant string) SysUserDao {
-	var dao SysUserDao
-	dao = SysUserDao{
-		M:     g.DB(tenant).Model("sys_user").Safe(),
-		DB:    g.DB(tenant),
-		Table: "sys_user",
-		Columns: sysUserColumns{
-			Id:          "id",
-			DeptId:      "dept_id",
-			UserName:    "user_name",
-			NickName:    "nick_name",
-			UserType:    "user_type",
-			Email:       "email",
-			Phone:       "phone",
-			Sex:         "sex",
-			Avatar:      "avatar",
-			Password:    "password",
-			LoginIp:     "login_ip",
-			LoginDate:   "login_date",
-			Remark:      "remark",
-			CreatedBy:   "created_by",
-			CreatedName: "created_name",
-			CreatedTime: "created_time",
-			UpdatedBy:   "updated_by",
-			UpdatedName: "updated_name",
-			UpdatedTime: "updated_time",
-			DeletedTime: "deleted_time",
-			Status:      "status",
-			UserSalt:    "user_salt",
-		},
-	}
-	return dao
-}
-
-// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy
-// of current DB object and with given context in it.
-// Note that this returned DB object can be used only once, so do not assign it to
-// a global or package variable for long using.
-func (d *SysUserDao) Ctx(ctx context.Context) *SysUserDao {
-	return &SysUserDao{M: d.M.Ctx(ctx)}
-}
-
-// As sets an alias name for current table.
-func (d *SysUserDao) As(as string) *SysUserDao {
-	return &SysUserDao{M: d.M.As(as)}
-}
-
-// TX sets the transaction for current operation.
-func (d *SysUserDao) TX(tx *gdb.TX) *SysUserDao {
-	return &SysUserDao{M: d.M.TX(tx)}
-}
-
-// Master marks the following operation on master node.
-func (d *SysUserDao) Master() *SysUserDao {
-	return &SysUserDao{M: d.M.Master()}
-}
-
-// Slave marks the following operation on slave node.
-// Note that it makes sense only if there's any slave node configured.
-func (d *SysUserDao) Slave() *SysUserDao {
-	return &SysUserDao{M: d.M.Slave()}
-}
-
-// Args sets custom arguments for model operation.
-func (d *SysUserDao) Args(args ...interface{}) *SysUserDao {
-	return &SysUserDao{M: d.M.Args(args...)}
-}
-
-// LeftJoin does "LEFT JOIN ... ON ..." statement on the model.
-// The parameter <table> can be joined table and its joined condition,
-// and also with its alias name, like:
-// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid")
-// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid")
-func (d *SysUserDao) LeftJoin(table ...string) *SysUserDao {
-	return &SysUserDao{M: d.M.LeftJoin(table...)}
-}
-
-// RightJoin does "RIGHT JOIN ... ON ..." statement on the model.
-// The parameter <table> can be joined table and its joined condition,
-// and also with its alias name, like:
-// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid")
-// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid")
-func (d *SysUserDao) RightJoin(table ...string) *SysUserDao {
-	return &SysUserDao{M: d.M.RightJoin(table...)}
-}
-
-// InnerJoin does "INNER JOIN ... ON ..." statement on the model.
-// The parameter <table> can be joined table and its joined condition,
-// and also with its alias name, like:
-// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid")
-// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid")
-func (d *SysUserDao) InnerJoin(table ...string) *SysUserDao {
-	return &SysUserDao{M: d.M.InnerJoin(table...)}
-}
-
-// Fields sets the operation fields of the model, multiple fields joined using char ','.
-// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
-func (d *SysUserDao) Fields(fieldNamesOrMapStruct ...interface{}) *SysUserDao {
-	return &SysUserDao{M: d.M.Fields(fieldNamesOrMapStruct...)}
-}
-
-// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','.
-// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
-func (d *SysUserDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *SysUserDao {
-	return &SysUserDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)}
-}
-
-// Option sets the extra operation option for the model.
-func (d *SysUserDao) Option(option int) *SysUserDao {
-	return &SysUserDao{M: d.M.Option(option)}
-}
-
-// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers
-// the data and where attributes for empty values.
-func (d *SysUserDao) OmitEmpty() *SysUserDao {
-	return &SysUserDao{M: d.M.OmitEmpty()}
-}
-
-// Filter marks filtering the fields which does not exist in the fields of the operated table.
-func (d *SysUserDao) Filter() *SysUserDao {
-	return &SysUserDao{M: d.M.Filter()}
-}
-
-// Where sets the condition statement for the model. The parameter <where> can be type of
-// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
-// multiple conditions will be joined into where statement using "AND".
-// Eg:
-// Where("uid=10000")
-// Where("uid", 10000)
-// Where("money>? AND name like ?", 99999, "vip_%")
-// Where("uid", 1).Where("name", "john")
-// Where("status IN (?)", g.Slice{1,2,3})
-// Where("age IN(?,?)", 18, 50)
-// Where(User{ Id : 1, UserName : "john"})
-func (d *SysUserDao) Where(where interface{}, args ...interface{}) *SysUserDao {
-	return &SysUserDao{M: d.M.Where(where, args...)}
-}
-
-// WherePri does the same logic as M.Where except that if the parameter <where>
-// is a single condition like int/string/float/slice, it treats the condition as the primary
-// key value. That is, if primary key is "id" and given <where> parameter as "123", the
-// WherePri function treats the condition as "id=123", but M.Where treats the condition
-// as string "123".
-func (d *SysUserDao) WherePri(where interface{}, args ...interface{}) *SysUserDao {
-	return &SysUserDao{M: d.M.WherePri(where, args...)}
-}
-
-// And adds "AND" condition to the where statement.
-func (d *SysUserDao) And(where interface{}, args ...interface{}) *SysUserDao {
-	return &SysUserDao{M: d.M.And(where, args...)}
-}
-
-// Or adds "OR" condition to the where statement.
-func (d *SysUserDao) Or(where interface{}, args ...interface{}) *SysUserDao {
-	return &SysUserDao{M: d.M.Or(where, args...)}
-}
-
-// Group sets the "GROUP BY" statement for the model.
-func (d *SysUserDao) Group(groupBy string) *SysUserDao {
-	return &SysUserDao{M: d.M.Group(groupBy)}
-}
-
-// Order sets the "ORDER BY" statement for the model.
-func (d *SysUserDao) Order(orderBy ...string) *SysUserDao {
-	return &SysUserDao{M: d.M.Order(orderBy...)}
-}
-
-// Limit sets the "LIMIT" statement for the model.
-// The parameter <limit> can be either one or two number, if passed two number is passed,
-// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
-// statement.
-func (d *SysUserDao) Limit(limit ...int) *SysUserDao {
-	return &SysUserDao{M: d.M.Limit(limit...)}
-}
-
-// Offset sets the "OFFSET" statement for the model.
-// It only makes sense for some databases like SQLServer, PostgreSQL, etc.
-func (d *SysUserDao) Offset(offset int) *SysUserDao {
-	return &SysUserDao{M: d.M.Offset(offset)}
-}
-
-// Page sets the paging number for the model.
-// The parameter <page> is started from 1 for paging.
-// Note that, it differs that the Limit function start from 0 for "LIMIT" statement.
-func (d *SysUserDao) Page(page, limit int) *SysUserDao {
-	return &SysUserDao{M: d.M.Page(page, limit)}
-}
-
-// Batch sets the batch operation number for the model.
-func (d *SysUserDao) Batch(batch int) *SysUserDao {
-	return &SysUserDao{M: d.M.Batch(batch)}
-}
-
-// Cache sets the cache feature for the model. It caches the result of the sql, which means
-// if there's another same sql request, it just reads and returns the result from cache, it
-// but not committed and executed into the database.
-//
-// If the parameter <duration> < 0, which means it clear the cache with given <name>.
-// If the parameter <duration> = 0, which means it never expires.
-// If the parameter <duration> > 0, which means it expires after <duration>.
-//
-// The optional parameter <name> is used to bind a name to the cache, which means you can later
-// control the cache like changing the <duration> or clearing the cache with specified <name>.
-//
-// Note that, the cache feature is disabled if the model is operating on a transaction.
-func (d *SysUserDao) Cache(duration time.Duration, name ...string) *SysUserDao {
-	return &SysUserDao{M: d.M.Cache(duration, name...)}
-}
-
-// Data sets the operation data for the model.
-// The parameter <data> can be type of string/map/gmap/slice/struct/*struct, etc.
-// Eg:
-// Data("uid=10000")
-// Data("uid", 10000)
-// Data(g.Map{"uid": 10000, "name":"john"})
-// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
-func (d *SysUserDao) Data(data ...interface{}) *SysUserDao {
-	return &SysUserDao{M: d.M.Data(data...)}
-}
-
-// All does "SELECT FROM ..." statement for the model.
-// It retrieves the records from table and returns the result as []*model.SysUser.
-// It returns nil if there's no record retrieved with the given conditions from table.
-//
-// The optional parameter <where> is the same as the parameter of M.Where function,
-// see M.Where.
-func (d *SysUserDao) All(where ...interface{}) ([]*model.SysUser, error) {
-	all, err := d.M.All(where...)
-	if err != nil {
-		return nil, err
-	}
-	var entities []*model.SysUser
-	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
-		return nil, err
-	}
-	return entities, nil
-}
-
-// One retrieves one record from table and returns the result as *model.SysUser.
-// It returns nil if there's no record retrieved with the given conditions from table.
-//
-// The optional parameter <where> is the same as the parameter of M.Where function,
-// see M.Where.
-func (d *SysUserDao) One(where ...interface{}) (*model.SysUser, error) {
-	one, err := d.M.One(where...)
-	if err != nil {
-		return nil, err
-	}
-	var entity *model.SysUser
-	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
-		return nil, err
-	}
-	return entity, nil
-}
-
-// FindOne retrieves and returns a single Record by M.WherePri and M.One.
-// Also see M.WherePri and M.One.
-func (d *SysUserDao) FindOne(where ...interface{}) (*model.SysUser, error) {
-	one, err := d.M.FindOne(where...)
-	if err != nil {
-		return nil, err
-	}
-	var entity *model.SysUser
-	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
-		return nil, err
-	}
-	return entity, nil
-}
-
-// FindAll retrieves and returns Result by by M.WherePri and M.All.
-// Also see M.WherePri and M.All.
-func (d *SysUserDao) FindAll(where ...interface{}) ([]*model.SysUser, error) {
-	all, err := d.M.FindAll(where...)
-	if err != nil {
-		return nil, err
-	}
-	var entities []*model.SysUser
-	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
-		return nil, err
-	}
-	return entities, nil
-}
-
-// Struct retrieves one record from table and converts it into given struct.
-// The parameter <pointer> should be type of *struct/**struct. If type **struct is given,
-// it can create the struct internally during converting.
-//
-// The optional parameter <where> is the same as the parameter of Model.Where function,
-// see Model.Where.
-//
-// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
-// from table and <pointer> is not nil.
-//
-// Eg:
-// user := new(User)
-// err  := dao.User.Where("id", 1).Struct(user)
-//
-// user := (*User)(nil)
-// err  := dao.User.Where("id", 1).Struct(&user)
-func (d *SysUserDao) Struct(pointer interface{}, where ...interface{}) error {
-	return d.M.Struct(pointer, where...)
-}
-
-// Structs retrieves records from table and converts them into given struct slice.
-// The parameter <pointer> should be type of *[]struct/*[]*struct. It can create and fill the struct
-// slice internally during converting.
-//
-// The optional parameter <where> is the same as the parameter of Model.Where function,
-// see Model.Where.
-//
-// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
-// from table and <pointer> is not empty.
-//
-// Eg:
-// users := ([]User)(nil)
-// err   := dao.User.Structs(&users)
-//
-// users := ([]*User)(nil)
-// err   := dao.User.Structs(&users)
-func (d *SysUserDao) Structs(pointer interface{}, where ...interface{}) error {
-	return d.M.Structs(pointer, where...)
-}
-
-// Scan automatically calls Struct or Structs function according to the type of parameter <pointer>.
-// It calls function Struct if <pointer> is type of *struct/**struct.
-// It calls function Structs if <pointer> is type of *[]struct/*[]*struct.
-//
-// The optional parameter <where> is the same as the parameter of Model.Where function,
-// see Model.Where.
-//
-// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil.
-//
-// Eg:
-// user  := new(User)
-// err   := dao.User.Where("id", 1).Scan(user)
-//
-// user  := (*User)(nil)
-// err   := dao.User.Where("id", 1).Scan(&user)
-//
-// users := ([]User)(nil)
-// err   := dao.User.Scan(&users)
-//
-// users := ([]*User)(nil)
-// err   := dao.User.Scan(&users)
-func (d *SysUserDao) Scan(pointer interface{}, where ...interface{}) error {
-	return d.M.Scan(pointer, where...)
-}
-
-// Chunk iterates the table with given size and callback function.
-func (d *SysUserDao) Chunk(limit int, callback func(entities []*model.SysUser, err error) bool) {
-	d.M.Chunk(limit, func(result gdb.Result, err error) bool {
-		var entities []*model.SysUser
-		err = result.Structs(&entities)
-		if err == sql.ErrNoRows {
-			return false
-		}
-		return callback(entities, err)
-	})
-}
-
-// LockUpdate sets the lock for update for current operation.
-func (d *SysUserDao) LockUpdate() *SysUserDao {
-	return &SysUserDao{M: d.M.LockUpdate()}
-}
-
-// LockShared sets the lock in share mode for current operation.
-func (d *SysUserDao) LockShared() *SysUserDao {
-	return &SysUserDao{M: d.M.LockShared()}
-}
-
-// Unscoped enables/disables the soft deleting feature.
-func (d *SysUserDao) Unscoped() *SysUserDao {
-	return &SysUserDao{M: d.M.Unscoped()}
-}

+ 0 - 36
opms_parent/app/dao/sys/sys_user.go

@@ -1,36 +0,0 @@
-// ============================================================================
-// This is auto-generated by gf cli tool only once. Fill this file as you wish.
-// ============================================================================
-
-package dao
-
-import (
-	"dashoo.cn/micro/app/dao/sys/internal"
-)
-
-// sysUserDao is the manager for logic model data accessing
-// and custom defined data operations functions management. You can define
-// methods on it to extend its functionality as you wish.
-type sysUserDao struct {
-	internal.SysUserDao
-}
-
-var (
-	// SysUser is globally public accessible object for table sys_user operations.
-	SysUser = sysUserDao{
-		internal.SysUser,
-	}
-)
-
-type SysUserDao struct {
-	internal.SysUserDao
-}
-
-func NewSysUserDao(tenant string) *SysUserDao {
-	dao := internal.NewSysUserDao(tenant)
-	return &SysUserDao{
-		dao,
-	}
-}
-
-// Fill with you ideas below.

+ 14 - 0
opms_parent/app/handler/contract/ctr_contract.go

@@ -100,6 +100,20 @@ func (c *CtrContract) Add(ctx context.Context, req *model.CtrContractAddReq, rsp
 	return nil
 }
 
+// Swagger:CtrContract 合同,测试tag 提交审核
+func (c *CtrContract) Commit(ctx context.Context, req *model.CtrContractCommitReq, rsp *comm_def.CommonMsg) error {
+	g.Log().Infof("CtrContract.Commit request %#v ", *req)
+	s, err := service.NewCtrContractService(ctx)
+	if err != nil {
+		return err
+	}
+	err = s.Commit(ctx, req)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
 // Swagger:CtrContract 合同,测试tag 更新合同
 func (c *CtrContract) Update(ctx context.Context, req *model.CtrContractUpdateReq, rsp *comm_def.CommonMsg) error {
 	g.Log().Infof("CtrContract.Update request %#v ", *req)

+ 14 - 11
opms_parent/app/handler/dingtalk/ding_event.go

@@ -169,6 +169,20 @@ func (h *DingHandler) handleBpmsInstanceChange(msg *message.MixMessage, ctx *din
 			return err.Error()
 		}
 		return "success"
+	case model.ContractCreate:
+		if msg.ProcessType == "finish" || msg.ProcessType == "terminate" {
+			err = contractSrv.ContractApplyApproval(ctx.SubsMessage.Ctx, instance, msg)
+			if err != nil {
+				glog.Error(err)
+				return err.Error()
+			}
+		}
+		err = s.Update(instance, msg)
+		if err != nil {
+			glog.Error(err)
+			return err.Error()
+		}
+		return "success"
 	case model.ProjectUpGrade:
 		if msg.ProcessType == "finish" || msg.ProcessType == "terminate" {
 			srv, err := projService.NewBusinessService(ctx.SubsMessage.Ctx)
@@ -245,17 +259,6 @@ func (h *DingHandler) handleBpmsInstanceChange(msg *message.MixMessage, ctx *din
 			return err.Error()
 		}
 		return "success"
-
-	case model.ContractCreate:
-		if msg.ProcessType == "finish" || msg.ProcessType == "terminate" {
-			//srv.Handle(instance, msg)
-		}
-		err = s.Update(instance, msg)
-		if err != nil {
-			glog.Error(err)
-			return err.Error()
-		}
-		return "success"
 	}
 
 	// 以下的代码需要调用钉钉接口查询数据,并且以下接口需要审批实例的数据

+ 46 - 0
opms_parent/app/handler/dingtalk/ding_upload.go

@@ -0,0 +1,46 @@
+package dingtalk
+
+import (
+	"context"
+	"fmt"
+	"time"
+
+	"dashoo.cn/common_definition/comm_def"
+	dingModel "dashoo.cn/micro/app/model/dingtalk"
+	"dashoo.cn/opms_libary/plugin/dingtalk"
+	"dashoo.cn/opms_libary/plugin/dingtalk/crypto"
+	"github.com/gogf/gf/util/gvalid"
+)
+
+type DingUploadHandler struct{}
+
+// Swagger:DingUpload 钉钉上传 获取签名
+func (h *DingUploadHandler) JsApiSign(ctx context.Context, req *dingModel.JsApiSignReq, resp *comm_def.CommonMsg) error {
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+
+	nonceStr := crypto.RandomString(10)
+	ts := time.Now().Unix()
+	accessToken, err := dingtalk.Client.Context.GetAccessToken()
+	if err != nil {
+		return fmt.Errorf("获取 accessToken 异常 %s", err.Error())
+	}
+	ticket, err := dingtalk.Client.GetJsapi().GetJsapiTicket(accessToken)
+	if err != nil {
+		return fmt.Errorf("获取 jsapiTicket 异常 %s", err.Error())
+	}
+
+	sign, err := dingtalk.Client.GetJsapi().Sign(ticket, nonceStr, req.Url, ts)
+	if err != nil {
+		return fmt.Errorf("生成签名异常 %s", err.Error())
+	}
+	resp.Data = dingModel.JsApiSignResp{
+		AgentId:   dingtalk.Client.Context.AgentId,
+		CorpId:    dingtalk.Client.Context.CorpId,
+		TimeStamp: ts,
+		NonceStr:  nonceStr,
+		Signature: sign,
+	}
+	return nil
+}

+ 16 - 0
opms_parent/app/model/contract/ctr_contract.go

@@ -122,3 +122,19 @@ type CtrContractTransferReq struct {
 	InchargeId   int    `json:"inchargeId"`   // 负责人ID
 	InchargeName string `json:"inchargeName"` // 负责人
 }
+
+type DingFileInfo struct {
+	SpaceId  string `json:"spaceId"`  // 空间ID
+	FileId   string `json:"fileId"`   // 文件ID
+	FileName string `json:"fileName"` //文件名
+	FileSize int    `json:"fileSize"` // 文件大小
+	FileType string `json:"fileType"` // 文件类型
+}
+
+type CtrContractCommitReq struct {
+	Id            int            `json:"id" v:"required#请输入Id"`
+	ContractModel string         `json:"contractModel"` // 合同模板 值可以是:大数模板, 客户模板
+	Terms         string         `json:"terms"`         // 条款情况 值可以是:接纳全部条款, 不接纳全部条款
+	PayTerms      string         `json:"payTerms"`      // 付款条件
+	File          []DingFileInfo `json:"file"`          // 附件
+}

+ 5 - 1
opms_parent/app/model/contract/internal/ctr_contract.go

@@ -15,9 +15,13 @@ type CtrContract struct {
 	ContractName      string      `orm:"contract_name"       json:"contractName"`      // 合同名称
 	CustId            int         `orm:"cust_id"             json:"custId"`            // 关联客户
 	CustName          string      `orm:"cust_name"           json:"custName"`          // 客户名称
+	CustProvinceId    int         `orm:"cust_province_id"    json:"custProvinceId"`    // 所在省ID
+	CustProvince      string      `orm:"cust_province"       json:"custProvince"`      // 所在省
+	CustCityId        int         `orm:"cust_city_id"        json:"custCityId"`        // 所在市ID
+	CustCity          string      `orm:"cust_city"           json:"custCity"`          // 所在市
 	NboId             int         `orm:"nbo_id"              json:"nboId"`             // 关联项目
 	NboName           string      `orm:"nbo_name"            json:"nboName"`           // 项目名称
-	ApproStatus       string      `orm:"appro_status"        json:"approStatus"`       // 审批状态
+	ApproStatus       string      `orm:"appro_status"        json:"approStatus"`       // 审核状态 10 待提交审核 20 待审核 30 审核已同意 40 审核已拒绝 50 审核已撤销
 	ContractType      string      `orm:"contract_type"       json:"contractType"`      // 合同类型
 	ContractAmount    float64     `orm:"contract_amount"     json:"contractAmount"`    // 合同金额
 	InvoiceAmount     float64     `orm:"invoice_amount"      json:"invoiceAmount"`     // 已开票金额

+ 12 - 0
opms_parent/app/model/dingtalk/ding_event.go

@@ -9,3 +9,15 @@ type DingReq struct {
 type DingEvent struct {
 	EventType string
 }
+
+type JsApiSignReq struct {
+	Url string `json:"url" v:"required#请输入当前页面 url"` // 当前页面 url
+}
+
+type JsApiSignResp struct {
+	AgentId   string `json:"agentId"`   // 必填,微应用ID
+	CorpId    string `json:"corpId"`    //必填,企业ID
+	TimeStamp int64  `json:"timeStamp"` // 必填,生成签名的时间戳
+	NonceStr  string `json:"nonceStr"`  // 必填,自定义固定字符串。
+	Signature string `json:"signature"` // 必填,签名
+}

+ 4 - 3
opms_parent/app/model/plat/internal/plat_task.go

@@ -14,12 +14,13 @@ type PlatTask struct {
 	TaskTitle        string      `orm:"task_title"         json:"taskTitle"`        // 任务标题
 	TaskType         string      `orm:"task_type"          json:"taskType"`         // 任务类型
 	TaskStatus       string      `orm:"task_status"        json:"taskStatus"`       // 任务状态(10发起  20进行中   30流程完成)
+	Source           string      `orm:"source"             json:"source"`           // 督办事项来源
 	IsOverdue        string      `orm:"is_overdue"         json:"isOverdue"`        // 是否超期(10否20是)
-	TaskStartDate    *gtime.Time `orm:"task_start_date"    json:"taskStartDate"`    // 任务开始时间
-	TaskEndDate      *gtime.Time `orm:"task_end_date"      json:"taskEndDate"`      // 任务结束时间
+	TaskStartDate    *gtime.Time `orm:"task_start_date"    json:"taskStartDate"`    // 发布时间
+	TaskEndDate      *gtime.Time `orm:"task_end_date"      json:"taskEndDate"`      // 要求完成时间
 	TaskDesc         string      `orm:"task_desc"          json:"taskDesc"`         // 任务说明
 	MainUserId       int         `orm:"main_user_id"       json:"mainUserId"`       // 负责人ID
-	OwnerUserId      string      `orm:"owner_user_id"      json:"ownerUserId"`      // 团队成员ID
+	OwnerUserId      string      `orm:"owner_user_id"      json:"ownerUserId"`      // 协办人ID
 	TaskLabel        string      `orm:"task_label"         json:"taskLabel"`        // 任务标签,号拼接
 	SupervisorUserId int         `orm:"supervisor_user_id" json:"supervisorUserId"` // 督办人ID
 	WatchUserId      int         `orm:"watch_user_id"      json:"watchUserId"`      // 监办人ID

+ 1 - 1
opms_parent/app/model/plat/internal/plat_task_handle.go

@@ -15,7 +15,7 @@ type PlatTaskHandle struct {
 	TaskStatus   string      `orm:"task_status"    json:"taskStatus"`   // 任务状态(10打开20关闭)
 	Step         int         `orm:"step"           json:"step"`         // 步骤号
 	MainUserId   int         `orm:"main_user_id"   json:"mainUserId"`   // 处理人ID
-	OwnerUserId  string      `orm:"owner_user_id"  json:"ownerUserId"`  // 团队成员ID
+	OwnerUserId  string      `orm:"owner_user_id"  json:"ownerUserId"`  // 协办人ID
 	HandleUserId int         `orm:"handle_user_id" json:"handleUserId"` // 处理人ID
 	HandleDate   *gtime.Time `orm:"handle_date"    json:"handleDate"`   // 处理时间
 	HandleStatus string      `orm:"handle_status"  json:"handleStatus"` // 处理结果(10接收20提交30审批通过40审批退回)

+ 4 - 3
opms_parent/app/model/plat/plat_task.go

@@ -40,14 +40,15 @@ type AddPlatTaskReq struct {
 	TaskTitle        string      `orm:"task_title"         json:"taskTitle"    v:"required#任务标题不能为空"`                     // 任务标题
 	TaskType         string      `orm:"task_type"          json:"taskType"    v:"required#任务类型不能为空"`                      // 任务类型
 	TaskStatus       string      `orm:"task_status"        json:"taskStatus"    v:"required#任务状态不能为空"`                    // 任务状态(10进行中20关闭)
+	Source           string      `orm:"source"             json:"source"`                                                 // 督办事项来源
 	IsOverdue        string      `orm:"is_overdue"         json:"isOverdue"`                                              // 是否超期(10否20是)
-	TaskStartDate    *gtime.Time `orm:"task_start_date"    json:"taskStartDate"    v:"required#任务开始时间不能为空"`               // 任务开始时间
-	TaskEndDate      *gtime.Time `orm:"task_end_date"      json:"taskEndDate"    v:"required#任务结束时间不能为空"`                 // 任务结束时间
+	TaskStartDate    *gtime.Time `orm:"task_start_date"    json:"taskStartDate"`                                          // 发布时间
+	TaskEndDate      *gtime.Time `orm:"task_end_date"      json:"taskEndDate"    v:"required#要求完成时间不能为空"`                 // 要求完成时间
 	TaskDesc         string      `orm:"task_desc"          json:"taskDesc"`                                               // 任务说明
 	SupervisorUserId int         `orm:"supervisor_user_id" json:"supervisorUserId"    v:"required|min:1#督办人不能为空|督办人不能为空"` // 督办人
 	WatchUserId      int         `orm:"watch_user_id"      json:"watchUserId"`                                            // 监办人
 	MainUserId       int         `orm:"main_user_id"       json:"mainUserId"    v:"required|min:1#负责人ID不能为空|负责人ID不能为空"`   // 负责人ID
-	OwnerUserId      string      `orm:"owner_user_id"      json:"ownerUserId"`                                            // 团队成员ID
+	OwnerUserId      string      `orm:"owner_user_id"      json:"ownerUserId"`                                            // 协办人ID
 	TaskLabel        string      `orm:"task_label"         json:"taskLabel"`                                              // 任务标签,号拼接
 	TargetId         int         `orm:"target_id"          json:"targetId"`                                               // 关联对象ID
 	TargetType       string      `orm:"target_type"        json:"targetType"`                                             // 关联对象类型(10客户,20项目,30合同,40回款)

+ 0 - 35
opms_parent/app/model/sys/internal/sys_user.go

@@ -1,35 +0,0 @@
-// ==========================================================================
-// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
-// ==========================================================================
-
-package internal
-
-import (
-	"github.com/gogf/gf/os/gtime"
-)
-
-// SysUser is the golang structure for table sys_user.
-type SysUser struct {
-	Id          int         `orm:"id,primary"   json:"id"`          // 用户ID
-	DeptId      int         `orm:"dept_id"      json:"deptId"`      // 部门ID
-	UserName    string      `orm:"user_name"    json:"userName"`    // 用户账号
-	NickName    string      `orm:"nick_name"    json:"nickName"`    // 用户昵称
-	UserType    string      `orm:"user_type"    json:"userType"`    // 用户类型(00系统用户)
-	Email       string      `orm:"email"        json:"email"`       // 用户邮箱
-	Phone       string      `orm:"phone"        json:"phone"`       // 手机号码
-	Sex         string      `orm:"sex"          json:"sex"`         // 用户性别(10男20女30未知)
-	Avatar      string      `orm:"avatar"       json:"avatar"`      // 头像地址
-	Password    string      `orm:"password"     json:"password"`    // 密码
-	LoginIp     string      `orm:"login_ip"     json:"loginIp"`     // 最后登录IP
-	LoginDate   *gtime.Time `orm:"login_date"   json:"loginDate"`   // 最后登录时间
-	Remark      string      `orm:"remark"       json:"remark"`      // 备注
-	CreatedBy   int         `orm:"created_by"   json:"createdBy"`   // 创建者
-	CreatedName string      `orm:"created_name" json:"createdName"` // 创建人
-	CreatedTime *gtime.Time `orm:"created_time" json:"createdTime"` // 创建时间
-	UpdatedBy   int         `orm:"updated_by"   json:"updatedBy"`   // 更新者
-	UpdatedName string      `orm:"updated_name" json:"updatedName"` // 更新人
-	UpdatedTime *gtime.Time `orm:"updated_time" json:"updatedTime"` // 更新时间
-	DeletedTime *gtime.Time `orm:"deleted_time" json:"deletedTime"` // 删除时间
-	Status      string      `orm:"status"       json:"status"`      // 帐号状态(10正常20停用)
-	UserSalt    string      `orm:"user_salt"    json:"userSalt"`    // 加密盐
-}

+ 0 - 12
opms_parent/app/model/sys/sys_user.go

@@ -1,12 +0,0 @@
-// ==========================================================================
-// This is auto-generated by gf cli tool. Fill this file as you wish.
-// ==========================================================================
-
-package model
-
-import (
-	"dashoo.cn/micro/app/model/sys/internal"
-)
-
-// SysUser is the golang structure for table sys_user.
-type SysUser internal.SysUser

+ 183 - 25
opms_parent/app/service/contract/ctr_contract.go

@@ -5,21 +5,28 @@ import (
 	"database/sql"
 	"encoding/json"
 	"fmt"
+	"strconv"
 	"time"
 
 	basedao "dashoo.cn/micro/app/dao/base"
 	dao "dashoo.cn/micro/app/dao/contract"
 	custdao "dashoo.cn/micro/app/dao/cust"
 	projdao "dashoo.cn/micro/app/dao/proj"
-	sysdao "dashoo.cn/micro/app/dao/sys"
 	model "dashoo.cn/micro/app/model/contract"
 	proj "dashoo.cn/micro/app/model/proj"
+	workflowModel "dashoo.cn/micro/app/model/workflow"
 	"dashoo.cn/micro/app/service"
+	projsrv "dashoo.cn/micro/app/service/proj"
+	workflowService "dashoo.cn/micro/app/service/workflow"
 
 	"dashoo.cn/opms_libary/micro_srv"
 	"dashoo.cn/opms_libary/myerrors"
+	"dashoo.cn/opms_libary/plugin/dingtalk/message"
+	"dashoo.cn/opms_libary/plugin/dingtalk/workflow"
 	"dashoo.cn/opms_libary/request"
+	"dashoo.cn/opms_libary/utils"
 	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/os/gtime"
 	"github.com/gogf/gf/util/gvalid"
 )
@@ -28,13 +35,13 @@ type CtrContractService struct {
 	Dao             *dao.CtrContractDao
 	ProjBusinessDao *projdao.ProjBusinessDao
 	CustomerDao     *custdao.CustCustomerDao
-	UserDao         *sysdao.SysUserDao
 	CtrProductDao   *dao.CtrContractProductDao
 	ProductDao      *basedao.BaseProductDao
 	DynamicsDao     *dao.CtrContractDynamicsDao
 
-	Tenant   string
-	userInfo request.UserInfo
+	Tenant    string
+	userInfo  request.UserInfo
+	DataScope g.Map `json:"dataScope"`
 }
 
 func NewCtrContractService(ctx context.Context) (*CtrContractService, error) {
@@ -52,12 +59,12 @@ func NewCtrContractService(ctx context.Context) (*CtrContractService, error) {
 		Dao:             dao.NewCtrContractDao(tenant),
 		ProjBusinessDao: projdao.NewProjBusinessDao(tenant),
 		CustomerDao:     custdao.NewCustCustomerDao(tenant),
-		UserDao:         sysdao.NewSysUserDao(tenant),
 		CtrProductDao:   dao.NewCtrContractProductDao(tenant),
 		ProductDao:      basedao.NewBaseProductDao(tenant),
 		DynamicsDao:     dao.NewCtrContractDynamicsDao(tenant),
 		Tenant:          tenant,
 		userInfo:        userInfo,
+		DataScope:       userInfo.DataScope,
 	}, nil
 }
 
@@ -140,9 +147,11 @@ func (s CtrContractService) DynamicsList(ctx context.Context, req *model.CtrCont
 }
 
 func (s CtrContractService) List(ctx context.Context, req *model.CtrContractListReq) (int, []*model.CtrContractListRsp, error) {
-	dao := s.Dao.DB.Table("ctr_contract a").
-		LeftJoin("cust_customer b", "a.cust_id=b.id").
-		Unscoped().Where("a.deleted_time is null")
+	ctx = context.WithValue(ctx, "contextService", s)
+	dao := s.Dao.DataScope(ctx, "incharge_id").As("a").
+		LeftJoin("cust_customer b", "a.cust_id=b.id").Unscoped().
+		Where("a.deleted_time is null")
+
 	if req.SearchText != "" {
 		likestr := fmt.Sprintf("%%%s%%", req.SearchText)
 		dao = dao.Where("(a.contract_code LIKE ? || a.contract_name LIKE ? || a.cust_name LIKE ? || a.nbo_name LIKE ?)", likestr, likestr, likestr, likestr)
@@ -233,7 +242,7 @@ func (s CtrContractService) List(ctx context.Context, req *model.CtrContractList
 func (s CtrContractService) BindProduct(tx *gdb.TX, id int, product []model.CtrAddProduct) error {
 	var amount float64
 	for _, p := range product {
-		amount += p.TranPrice
+		amount += (p.TranPrice * float64(p.ProdNum))
 	}
 
 	_, err := tx.Delete("ctr_contract_product", "contract_id = ?", id)
@@ -309,40 +318,47 @@ func (s CtrContractService) Add(ctx context.Context, req *model.CtrContractAddRe
 		return 0, myerrors.TipsError(validErr.Current().Error())
 	}
 
-	sequence, err := service.Sequence(s.Dao.DB, "contract_code")
+	c, err := s.Dao.Where("contract_name = ?", req.ContractName).One()
 	if err != nil {
 		return 0, err
 	}
-	if req.ContractCode == "" {
-		req.ContractCode = fmt.Sprintf("DS%s%s%s", req.ContractType, time.Now().Format("0601"), sequence)
+	if c != nil {
+		return 0, myerrors.TipsError(fmt.Sprintf("合同名称:%s 已存在", req.ContractName))
 	}
-
-	c, err := s.Dao.Where("contract_code = ?", req.ContractCode).One()
+	nbo, err := s.ProjBusinessDao.Where("id = ?", req.NboId).One()
 	if err != nil {
 		return 0, err
 	}
-	if c != nil {
-		return 0, myerrors.TipsError(fmt.Sprintf("合同编号:%s 已存在", req.ContractCode))
+	if nbo == nil {
+		return 0, myerrors.TipsError("项目不存在")
 	}
-	c, err = s.Dao.Where("contract_name = ?", req.ContractName).One()
+	c, err = s.Dao.Where("nbo_id = ?", req.NboId).One()
 	if err != nil {
 		return 0, err
 	}
 	if c != nil {
-		return 0, myerrors.TipsError(fmt.Sprintf("合同名称:%s 已存在", req.ContractName))
+		return 0, myerrors.TipsError("所选项目已添加合同")
 	}
-	nbo, err := s.ProjBusinessDao.Where("id = ?", req.NboId).One()
+
+	sequence, err := service.Sequence(s.Dao.DB, "contract_code")
 	if err != nil {
 		return 0, err
 	}
-	if nbo == nil {
-		return 0, myerrors.TipsError("项目不存在")
+	if req.ContractCode == "" {
+		req.ContractCode = fmt.Sprintf("DS%s%s%s", req.ContractType, time.Now().Format("0601"), sequence)
+	}
+	c, err = s.Dao.Where("contract_code = ?", req.ContractCode).One()
+	if err != nil {
+		return 0, err
+	}
+	if c != nil {
+		return 0, myerrors.TipsError(fmt.Sprintf("合同编号:%s 已存在", req.ContractCode))
 	}
+
 	var contractAmount float64
 	for _, p := range req.Product {
-		contractAmount += p.TranPrice
+		contractAmount += (p.TranPrice * float64(p.ProdNum))
 	}
-
 	ctr := model.CtrContract{
 		ContractCode:      req.ContractCode,
 		ContractName:      req.ContractName,
@@ -350,7 +366,7 @@ func (s CtrContractService) Add(ctx context.Context, req *model.CtrContractAddRe
 		CustName:          nbo.CustName,
 		NboId:             nbo.Id,
 		NboName:           nbo.NboName,
-		ApproStatus:       "",
+		ApproStatus:       "10",
 		ContractType:      req.ContractType,
 		ContractAmount:    contractAmount,
 		InvoiceAmount:     0,
@@ -389,12 +405,154 @@ func (s CtrContractService) Add(ctx context.Context, req *model.CtrContractAddRe
 		if err != nil {
 			return err
 		}
+		_, err = tx.Update("proj_business", map[string]interface{}{
+			"nbo_type": projsrv.StatusDeal,
+		}, "id = ?", nbo.Id)
+		if err != nil {
+			return err
+		}
 		id = int(ctrid)
 		return nil
 	})
 	return id, txerr
 }
 
+var ContractApplyProcessCode = "PROC-7057E20A-2066-4644-9B35-9331E4DA912C" // 创建合同
+
+func (s CtrContractService) Commit(ctx context.Context, req *model.CtrContractCommitReq) error {
+	validErr := gvalid.CheckStruct(ctx, req, nil)
+	if validErr != nil {
+		return myerrors.TipsError(validErr.Current().Error())
+	}
+	if !(req.ContractModel == "大数模板" || req.ContractModel == "客户模板") {
+		return myerrors.TipsError("合同模板不合法")
+	}
+	if !(req.Terms == "接纳全部条款" || req.Terms == "不接纳全部条款") {
+		return myerrors.TipsError("条款情况不合法")
+	}
+	if req.PayTerms == "" {
+		return myerrors.TipsError("付款条件不能为空")
+	}
+	if len(req.File) == 0 {
+		return myerrors.TipsError("附件不能为空")
+	}
+
+	ent, err := s.Dao.Where("id = ?", req.Id).One()
+	if err != nil {
+		return err
+	}
+	if ent == nil {
+		return myerrors.TipsError(fmt.Sprintf("合同不存在: %d", req.Id))
+	}
+
+	fileinfoByte, err := json.Marshal(req.File)
+	if err != nil {
+		return err
+	}
+
+	workflowSrv, err := workflowService.NewFlowService(ctx)
+	if err != nil {
+		return err
+	}
+	bizCode := strconv.Itoa(ent.Id)
+	_, err = workflowSrv.StartProcessInstance(bizCode, "30", "", &workflow.StartProcessInstanceRequest{
+		ProcessCode: &ContractApplyProcessCode,
+		FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
+			{
+				Id:    utils.String("DDSelectField_ESX8H30W3VK0"),
+				Name:  utils.String("合同模板"),
+				Value: utils.String(req.ContractModel),
+			},
+			{
+				Id:    utils.String("DDSelectField_13IQX96C2KAK0"),
+				Name:  utils.String("条款情况"),
+				Value: utils.String(req.Terms),
+			},
+			{
+				Id:    utils.String("TextField_1A5SA7VOG5TS0"),
+				Name:  utils.String("合同编号"),
+				Value: utils.String(ent.ContractCode),
+			},
+			{
+				Id:    utils.String("TextField_1EX61DPS3LA80"),
+				Name:  utils.String("客户名称"),
+				Value: utils.String(ent.CustName),
+			},
+			{
+				Id:    utils.String("MoneyField_X1XV4KIR0GW0"),
+				Name:  utils.String("合同金额(元)"),
+				Value: utils.String(strconv.FormatFloat(ent.ContractAmount, 'f', 2, 64)),
+			},
+			{
+				Id:    utils.String("TextareaField_1WZ5ILKBUVSW0"),
+				Name:  utils.String("付款条件"),
+				Value: utils.String(req.PayTerms),
+			},
+			{
+				Id:   utils.String("DDAttachment_1051KJYC3MBK0"),
+				Name: utils.String("附件"),
+				// Details: productForm,
+				Value: utils.String(string(fileinfoByte)),
+			},
+		},
+	})
+	if err != nil {
+		return err
+	}
+
+	_, err = s.Dao.Where("id = ?", ent.Id).Data(map[string]interface{}{
+		"appro_status": 20,
+	}).Update()
+	return err
+}
+
+func ContractApplyApproval(ctx context.Context, flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
+	tenant, err := micro_srv.GetTenant(ctx)
+	if err != nil {
+		return fmt.Errorf("获取租户码异常:%s", err.Error())
+	}
+	contractDao := dao.NewCtrContractDao(tenant)
+
+	contractId, err := strconv.Atoi(flow.BizCode)
+	if err != nil {
+		return fmt.Errorf("创建合同审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
+	}
+	contract, err := contractDao.Where("id = ?", contractId).One()
+	if err != nil {
+		return err
+	}
+	if contract == nil {
+		return fmt.Errorf("合同不存在:%s Id: %d", flow.BizCode, flow.Id)
+	}
+
+	if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
+		return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
+	}
+	if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
+		return fmt.Errorf("无法识别的 Result :%s", msg.Result)
+	}
+
+	if msg.ProcessType == "terminate" {
+		_, err = contractDao.Where("id = ?", contractId).Data(map[string]interface{}{
+			"appro_status": "50",
+		}).Update()
+		return err
+	}
+
+	pass := msg.Result == "agree"
+	if !pass {
+		_, err = contractDao.Where("id = ?", contractId).Data(map[string]interface{}{
+			"appro_status": "40",
+		}).Update()
+		return err
+	}
+
+	_, err = contractDao.Where("id = ?", contractId).Data(map[string]interface{}{
+		"appro_status": "30",
+	}).Update()
+	return err
+}
+
 func (s CtrContractService) Update(ctx context.Context, req *model.CtrContractUpdateReq) error {
 	validErr := gvalid.CheckStruct(ctx, req, nil)
 	if validErr != nil {
@@ -506,7 +664,7 @@ func (s CtrContractService) Update(ctx context.Context, req *model.CtrContractUp
 	if req.Product != nil {
 		var contractAmount float64
 		for _, p := range *req.Product {
-			contractAmount += p.TranPrice
+			contractAmount += (p.TranPrice * float64(p.ProdNum))
 		}
 		toupdate["contract_amount"] = contractAmount
 	}

+ 1 - 16
opms_parent/app/service/contract/ctr_contract_invoice.go

@@ -10,7 +10,6 @@ import (
 
 	dao "dashoo.cn/micro/app/dao/contract"
 	customerDao "dashoo.cn/micro/app/dao/cust"
-	sysDao "dashoo.cn/micro/app/dao/sys"
 	model "dashoo.cn/micro/app/model/contract"
 	workflowModel "dashoo.cn/micro/app/model/workflow"
 	workflowService "dashoo.cn/micro/app/service/workflow"
@@ -30,7 +29,6 @@ type CtrContractInvoiceService struct {
 	Dao         *dao.CtrContractInvoiceDao
 	ContractDao *dao.CtrContractDao
 	CustomerDao *customerDao.CustCustomerDao
-	UserDao     *sysDao.SysUserDao
 	ctrSrv      *CtrContractService
 	Tenant      string
 	userInfo    request.UserInfo
@@ -55,7 +53,6 @@ func NewCtrContractInvoiceService(ctx context.Context) (*CtrContractInvoiceServi
 		Dao:         dao.NewCtrContractInvoiceDao(tenant),
 		ContractDao: dao.NewCtrContractDao(tenant),
 		CustomerDao: customerDao.NewCustCustomerDao(tenant),
-		UserDao:     sysDao.NewSysUserDao(tenant),
 		ctrSrv:      ctrSrv,
 		Tenant:      tenant,
 		userInfo:    userInfo,
@@ -391,7 +388,7 @@ func (s CtrContractInvoiceService) InvoiceApply(ctx context.Context, req *model.
 		strconv.Itoa(invoice.Id),
 		strconv.Itoa(s.userInfo.Id),
 	}, ":")
-	_, err = workflowSrv.StartProcessInstance(bizCode, "31", &workflow.StartProcessInstanceRequest{
+	_, err = workflowSrv.StartProcessInstance(bizCode, "31", "", &workflow.StartProcessInstanceRequest{
 		ProcessCode: &InvoiceApplyProcessCode,
 		FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
 			{
@@ -453,7 +450,6 @@ func InvoiceApplyApproval(ctx context.Context, flow *workflowModel.PlatWorkflow,
 		return fmt.Errorf("获取租户码异常:%s", err.Error())
 	}
 	invoiceDao := dao.NewCtrContractInvoiceDao(tenant)
-	userDao := sysDao.NewSysUserDao(tenant)
 
 	bizCode := strings.Split(flow.BizCode, ":")
 	if len(bizCode) != 2 {
@@ -463,17 +459,6 @@ func InvoiceApplyApproval(ctx context.Context, flow *workflowModel.PlatWorkflow,
 	if err != nil {
 		return fmt.Errorf("申请发票审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
 	}
-	userId, err := strconv.Atoi(bizCode[1])
-	if err != nil {
-		return fmt.Errorf("申请发票审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
-	}
-	user, err := userDao.Where("id = ?", userId).One()
-	if err != nil {
-		return err
-	}
-	if user == nil {
-		return fmt.Errorf("用户不存在:%s Id: %d", flow.BizCode, flow.Id)
-	}
 	invoice, err := invoiceDao.Where("id = ?", invoiceId).One()
 	if err != nil {
 		return err

+ 19 - 0
opms_parent/app/service/contract/ctr_contract_test.go

@@ -37,3 +37,22 @@ func TestAssignInvoiceApplyApproval(t *testing.T) {
 		panic(err)
 	}
 }
+
+func TestContractApplyApproval(t *testing.T) {
+	ctx := fakeCtx(context.Background(), testTenant)
+
+	instance := modelWorkflow.PlatWorkflow{}
+	err := g.DB(testTenant).Table("plat_workflow").Where("id = ?", 47).Struct(&instance)
+	if err != nil {
+		panic(err)
+	}
+	err = ContractApplyApproval(ctx, &instance, &message.MixMessage{
+		ProcessType: "finish",
+		// ProcessType: "terminate",
+		// Result: "agree",
+		Result: "refuse",
+	})
+	if err != nil {
+		panic(err)
+	}
+}

+ 80 - 58
opms_parent/app/service/cust/cust_customer.go

@@ -3,6 +3,7 @@ package cust
 import (
 	"bytes"
 	"context"
+	"encoding/json"
 	"fmt"
 	"math"
 	"strconv"
@@ -26,7 +27,6 @@ import (
 
 	"dashoo.cn/micro/app/dao/cust"
 	platdao "dashoo.cn/micro/app/dao/plat"
-	sysDao "dashoo.cn/micro/app/dao/sys"
 	model "dashoo.cn/micro/app/model/cust"
 	workflowModel "dashoo.cn/micro/app/model/workflow"
 	"dashoo.cn/micro/app/service"
@@ -40,7 +40,6 @@ type CustomerService struct {
 	DynamicsDao    *cust.CustCustomerDynamicsDao
 	ContactDao     *cust.CustCustomerContactDao
 	FollowDao      *platdao.PlatFollowupDao
-	UserDao        *sysDao.SysUserDao
 	BelongServer   *CustomerbelongService
 	ContanctServer *CustomercontactService
 }
@@ -64,7 +63,6 @@ func NewCustomerService(ctx context.Context) (svc *CustomerService, err error) {
 	svc.FollowDao = platdao.NewPlatFollowupDao(svc.Tenant)
 	svc.BelongServer, _ = NewCustomerBelongService(ctx)
 	svc.ContanctServer, _ = NewCustomerContactService(ctx)
-	svc.UserDao = sysDao.NewSysUserDao(svc.Tenant)
 	return svc, nil
 }
 
@@ -326,13 +324,20 @@ func (s *CustomerService) AssignCustomerRequest(ctx context.Context, req *model.
 		}
 	}
 
+	remark, err := json.Marshal(map[string]string{
+		"applyUserId":   strconv.Itoa(s.GetCxtUserId()),
+		"applyUserName": s.GetCxtUserName(),
+	})
+	if err != nil {
+		return err
+	}
 	workflowSrv, err := workflowService.NewFlowService(ctx)
 	if err != nil {
 		return err
 	}
 	for _, u := range data {
 		bizCode := strconv.Itoa(u.Id) + ":" + strconv.Itoa(s.GetCxtUserId())
-		_, err = workflowSrv.StartProcessInstance(bizCode, "11", &workflow.StartProcessInstanceRequest{
+		_, err = workflowSrv.StartProcessInstance(bizCode, "11", string(remark), &workflow.StartProcessInstanceRequest{
 			ProcessCode: &AssignCustomerRequestProcessCode,
 			FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
 				{
@@ -388,6 +393,12 @@ func (s *CustomerService) AssignCustomerRequest(ctx context.Context, req *model.
 }
 
 func (s *CustomerService) AssignCustomerRequestApproval(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
+	remark := map[string]string{}
+	err := json.Unmarshal([]byte(flow.Remark), &remark)
+	if err != nil {
+		return err
+	}
+	userName := remark["applyUserName"]
 	bizCode := strings.Split(flow.BizCode, ":")
 	if len(bizCode) != 2 {
 		return fmt.Errorf("客户领取审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
@@ -400,13 +411,6 @@ func (s *CustomerService) AssignCustomerRequestApproval(flow *workflowModel.Plat
 	if err != nil {
 		return fmt.Errorf("客户领取审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
 	}
-	user, err := s.UserDao.Where("id = ?", userId).One()
-	if err != nil {
-		return err
-	}
-	if user == nil {
-		return fmt.Errorf("用户不存在:%s Id: %d", flow.BizCode, flow.Id)
-	}
 	cust, err := s.Dao.Where("id = ?", custId).One()
 	if err != nil {
 		return err
@@ -439,15 +443,15 @@ func (s *CustomerService) AssignCustomerRequestApproval(flow *workflowModel.Plat
 		return err
 	}
 
-	s.CxtUser = &request.UserInfo{Id: user.Id, UserName: user.NickName}
-	err = s.ChangeCustBelong([]int64{int64(custId)}, int64(userId), user.NickName)
+	s.CxtUser = &request.UserInfo{Id: userId, UserName: userName}
+	err = s.ChangeCustBelong([]int64{int64(custId)}, int64(userId), remark["applyUserName"])
 	if err != nil {
 		return err
 	}
 	err = s.BatchCreatebelong([]*model.CustCustomer{cust}, &model.AssignCustomerReq{
 		Ids:       []int64{int64(custId)},
-		SalesId:   int64(user.Id),
-		SalesName: user.NickName,
+		SalesId:   int64(userId),
+		SalesName: userName,
 		Remark:    "",
 		Receive:   Receive,
 	})
@@ -455,9 +459,9 @@ func (s *CustomerService) AssignCustomerRequestApproval(flow *workflowModel.Plat
 		return err
 	}
 
-	s.CxtUser = &request.UserInfo{Id: user.Id, UserName: user.NickName}
+	s.CxtUser = &request.UserInfo{Id: userId, UserName: userName}
 	return s.CreateDynamics("领取客户", map[string]interface{}{
-		"userId": user.Id,
+		"userId": userId,
 		"custId": cust.Id,
 	}, int64(cust.Id))
 }
@@ -493,13 +497,21 @@ func (s *CustomerService) MoveToPublicRequest(ctx context.Context, req *model.Mo
 		}
 	}
 
+	remark, err := json.Marshal(map[string]string{
+		"applyUserId":   strconv.Itoa(s.GetCxtUserId()),
+		"applyUserName": s.GetCxtUserName(),
+	})
+	if err != nil {
+		return err
+	}
+
 	workflowSrv, err := workflowService.NewFlowService(ctx)
 	if err != nil {
 		return err
 	}
 	for _, u := range data {
 		bizCode := strconv.Itoa(u.Id) + ":" + strconv.Itoa(s.GetCxtUserId())
-		_, err = workflowSrv.StartProcessInstance(bizCode, "12", &workflow.StartProcessInstanceRequest{
+		_, err = workflowSrv.StartProcessInstance(bizCode, "12", string(remark), &workflow.StartProcessInstanceRequest{
 			ProcessCode: &MoveToPubicRequestProcessCode,
 			FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
 				{
@@ -555,6 +567,12 @@ func (s *CustomerService) MoveToPublicRequest(ctx context.Context, req *model.Mo
 
 // 移入公海回调
 func (s *CustomerService) MoveToPublicApproval(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
+	remark := map[string]string{}
+	err := json.Unmarshal([]byte(flow.Remark), &remark)
+	if err != nil {
+		return err
+	}
+	userName := remark["applyUserName"]
 	bizCode := strings.Split(flow.BizCode, ":")
 	if len(bizCode) != 2 {
 		return fmt.Errorf("客户移回审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
@@ -567,13 +585,6 @@ func (s *CustomerService) MoveToPublicApproval(flow *workflowModel.PlatWorkflow,
 	if err != nil {
 		return fmt.Errorf("客户移回审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
 	}
-	user, err := s.UserDao.Where("id = ?", userId).One()
-	if err != nil {
-		return err
-	}
-	if user == nil {
-		return fmt.Errorf("用户不存在:%s Id: %d", flow.BizCode, flow.Id)
-	}
 	cust, err := s.Dao.Where("id = ?", custId).One()
 	if err != nil {
 		return err
@@ -613,21 +624,15 @@ func (s *CustomerService) MoveToPublicApproval(flow *workflowModel.PlatWorkflow,
 			"sales_id":     0,
 			"dept_id":      0,
 			"dept_name":    "",
-			"create_time":  now,
-			"updated_by":   user.Id,
-			"updated_name": user.NickName,
 			"updated_time": now,
 		}).Where("id = ?", cust.Id).Update()
 		if err != nil {
 			return err
 		}
 		//更新销售归属表结束时间
-		_, err = s.BelongDao.TX(tx).Data(
-			g.Map{
-				"updated_by":   user.Id,
-				"updated_name": user.NickName,
-				"end_date":     now,
-			}).Where("cust_id = ?", cust.Id).Update()
+		_, err = s.BelongDao.TX(tx).Data(g.Map{
+			"end_date": now,
+		}).Where("cust_id = ?", cust.Id).Update()
 		if err != nil {
 			return err
 		}
@@ -637,9 +642,9 @@ func (s *CustomerService) MoveToPublicApproval(flow *workflowModel.PlatWorkflow,
 		return err
 	}
 
-	s.CxtUser = &request.UserInfo{Id: user.Id, UserName: user.NickName}
+	s.CxtUser = &request.UserInfo{Id: userId, UserName: userName}
 	return s.CreateDynamics("移入公海", map[string]interface{}{
-		"userId": user.Id,
+		"userId": userId,
 		"custId": cust.Id,
 	}, int64(cust.Id))
 }
@@ -675,6 +680,16 @@ func (s *CustomerService) TransCustomerRequest(ctx context.Context, req *model.A
 		}
 	}
 
+	remark, err := json.Marshal(map[string]string{
+		"applyUserId":   strconv.Itoa(s.GetCxtUserId()),
+		"applyUserName": s.GetCxtUserName(),
+		"toUserId":      strconv.FormatInt(req.SalesId, 10),
+		"toUserName":    req.SalesName,
+	})
+	if err != nil {
+		return err
+	}
+
 	workflowSrv, err := workflowService.NewFlowService(ctx)
 	if err != nil {
 		return err
@@ -685,7 +700,7 @@ func (s *CustomerService) TransCustomerRequest(ctx context.Context, req *model.A
 			strconv.Itoa(s.GetCxtUserId()),
 			strconv.FormatInt(req.SalesId, 10),
 		}, ":")
-		_, err = workflowSrv.StartProcessInstance(bizCode, "13", &workflow.StartProcessInstanceRequest{
+		_, err = workflowSrv.StartProcessInstance(bizCode, "13", string(remark), &workflow.StartProcessInstanceRequest{
 			ProcessCode: &TransCustomerRequestProcessCode,
 			FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
 				{
@@ -741,6 +756,13 @@ func (s *CustomerService) TransCustomerRequest(ctx context.Context, req *model.A
 
 // 转移客户回调
 func (s *CustomerService) TransCustomerApproval(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
+	remark := map[string]string{}
+	err := json.Unmarshal([]byte(flow.Remark), &remark)
+	if err != nil {
+		return err
+	}
+	userName := remark["applyUserName"]
+	toUserName := remark["toUserName"]
 	bizCode := strings.Split(flow.BizCode, ":")
 	if len(bizCode) != 3 {
 		return fmt.Errorf("转移客户审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
@@ -757,20 +779,20 @@ func (s *CustomerService) TransCustomerApproval(flow *workflowModel.PlatWorkflow
 	if err != nil {
 		return fmt.Errorf("转移客户审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
 	}
-	user, err := s.UserDao.Where("id = ?", userId).One()
-	if err != nil {
-		return err
-	}
-	if user == nil {
-		return fmt.Errorf("用户不存在:%s Id: %d", flow.BizCode, flow.Id)
-	}
-	toUser, err := s.UserDao.Where("id = ?", toUserId).One()
-	if err != nil {
-		return err
-	}
-	if toUser == nil {
-		return fmt.Errorf("用户不存在:%s Id: %d", flow.BizCode, flow.Id)
-	}
+	// user, err := s.UserDao.Where("id = ?", userId).One()
+	// if err != nil {
+	// 	return err
+	// }
+	// if user == nil {
+	// 	return fmt.Errorf("用户不存在:%s Id: %d", flow.BizCode, flow.Id)
+	// }
+	// toUser, err := s.UserDao.Where("id = ?", toUserId).One()
+	// if err != nil {
+	// 	return err
+	// }
+	// if toUser == nil {
+	// 	return fmt.Errorf("用户不存在:%s Id: %d", flow.BizCode, flow.Id)
+	// }
 	cust, err := s.Dao.Where("id = ?", custId).One()
 	if err != nil {
 		return err
@@ -801,15 +823,15 @@ func (s *CustomerService) TransCustomerApproval(flow *workflowModel.PlatWorkflow
 		return err
 	}
 
-	s.CxtUser = &request.UserInfo{Id: user.Id, UserName: user.NickName}
-	err = s.ChangeCustBelong([]int64{int64(custId)}, int64(toUserId), toUser.NickName)
+	s.CxtUser = &request.UserInfo{Id: userId, UserName: userName}
+	err = s.ChangeCustBelong([]int64{int64(custId)}, int64(toUserId), toUserName)
 	if err != nil {
 		return err
 	}
 	err = s.BatchCreatebelong([]*model.CustCustomer{cust}, &model.AssignCustomerReq{
 		Ids:       []int64{int64(custId)},
-		SalesId:   int64(toUser.Id),
-		SalesName: toUser.NickName,
+		SalesId:   int64(toUserId),
+		SalesName: toUserName,
 		Remark:    "",
 		Receive:   OperaTion,
 	})
@@ -817,11 +839,11 @@ func (s *CustomerService) TransCustomerApproval(flow *workflowModel.PlatWorkflow
 		return err
 	}
 
-	s.CxtUser = &request.UserInfo{Id: user.Id, UserName: user.NickName}
+	s.CxtUser = &request.UserInfo{Id: userId, UserName: userName}
 	return s.CreateDynamics("转移客户", map[string]interface{}{
-		"userId":   user.Id,
+		"userId":   userId,
 		"custId":   cust.Id,
-		"toUserId": toUser.Id,
+		"toUserId": toUserId,
 	}, int64(cust.Id))
 }
 

+ 3 - 3
opms_parent/app/service/cust/cust_customer_test.go

@@ -27,7 +27,7 @@ func TestAssignCustomerRequestApproval(t *testing.T) {
 		panic(err)
 	}
 	instance := modelWorkflow.PlatWorkflow{}
-	err = g.DB(testTenant).Table("plat_workflow").Where("id = ?", 55).Struct(&instance)
+	err = g.DB(testTenant).Table("plat_workflow").Where("id = ?", 66).Struct(&instance)
 	if err != nil {
 		panic(err)
 	}
@@ -49,7 +49,7 @@ func TestAssignMoveToPublicApproval(t *testing.T) {
 		panic(err)
 	}
 	instance := modelWorkflow.PlatWorkflow{}
-	err = g.DB(testTenant).Table("plat_workflow").Where("id = ?", 25).Struct(&instance)
+	err = g.DB(testTenant).Table("plat_workflow").Where("id = ?", 65).Struct(&instance)
 	if err != nil {
 		panic(err)
 	}
@@ -71,7 +71,7 @@ func TestAssignTransCustomerApproval(t *testing.T) {
 		panic(err)
 	}
 	instance := modelWorkflow.PlatWorkflow{}
-	err = g.DB(testTenant).Table("plat_workflow").Where("id = ?", 27).Struct(&instance)
+	err = g.DB(testTenant).Table("plat_workflow").Where("id = ?", 67).Struct(&instance)
 	if err != nil {
 		panic(err)
 	}

+ 14 - 8
opms_parent/app/service/plat/plat_task.go

@@ -139,11 +139,14 @@ func (s *taskService) Export(req *model.ExportReq) (content *model.ExportContent
 					}
 					f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), data)
 				}
+				if value == "督办事项来源" {
+					f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.Source)
+				}
 				if value == "超期" {
 					data := ""
-					if item.TaskStatus == "10" {
+					if gtime.Now().Format("Y-m-d H:i:s") <= item.TaskEndDate.Format("Y-m-d 23:59:59") {
 						data = "否"
-					} else if item.TaskStatus == "20" {
+					} else {
 						data = "是"
 					}
 					f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), data)
@@ -157,7 +160,7 @@ func (s *taskService) Export(req *model.ExportReq) (content *model.ExportContent
 				if value == "负责人" {
 					f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), userMap[item.MainUserId])
 				}
-				if value == "团队成员" {
+				if value == "协办人" {
 					names := ""
 					if item.OwnerUserId != "" {
 						ids := strings.Split(item.OwnerUserId, ",")
@@ -175,11 +178,11 @@ func (s *taskService) Export(req *model.ExportReq) (content *model.ExportContent
 				if value == "督办人" {
 					f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), userMap[item.SupervisorUserId])
 				}
-				if value == "开始时间" {
-					f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TaskStartDate.Format("Y-m-d H:i:s"))
+				if value == "发布时间" {
+					f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TaskStartDate.Format("Y-m-d"))
 				}
-				if value == "结束时间" {
-					f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TaskEndDate.Format("Y-m-d H:i:s"))
+				if value == "要求完成时间" {
+					f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.TaskEndDate.Format("Y-m-d"))
 				}
 				if value == "创建时间" {
 					f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(lineNum+2), item.CreatedTime.Format("Y-m-d H:i:s"))
@@ -216,10 +219,13 @@ func (s *taskService) Create(req *model.AddPlatTaskReq) (err error) {
 	if err = gconv.Struct(req, platTask); err != nil {
 		return
 	}
+
+	// 初始数据
 	platTask.IsOverdue = "10" // 是否超期(10否20是)
-	if platTask.TaskStartDate == nil {
+	if platTask.TaskStartDate == nil || platTask.TaskStartDate.IsZero() {
 		platTask.TaskStartDate = gtime.Now()
 	}
+
 	// 填充创建信息
 	service.SetCreatedInfo(platTask, s.GetCxtUserId(), s.GetCxtUserName())
 	// 填充更新信息

+ 4 - 4
opms_parent/app/service/proj/business.go

@@ -355,7 +355,7 @@ func (p *businessService) BusinessTransfer(req *model.BusinessTransferReq) error
 
 		// OMS项目转移 审批
 		bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
-		_, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectTransfer, &workflow.StartProcessInstanceRequest{
+		_, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectTransfer, "", &workflow.StartProcessInstanceRequest{
 			ProcessCode: &BusinessTransferRequestProcessCode,
 			FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
 				{
@@ -535,7 +535,7 @@ func (p *businessService) BusinessUpgrade(req *model.BusinessUpgradeReq) error {
 		}
 		// OMS项目降级 审批
 		bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
-		_, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectUpGrade, &workflow.StartProcessInstanceRequest{
+		_, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectUpGrade, "", &workflow.StartProcessInstanceRequest{
 			ProcessCode: &BusinessUpgradeRequestProcessCode,
 			FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
 				{
@@ -698,7 +698,7 @@ func (p *businessService) BusinessDowngrade(req *model.BusinessDowngradeReq) err
 		}
 		// OMS项目降级 审批
 		bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
-		_, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectDownGrade, &workflow.StartProcessInstanceRequest{
+		_, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectDownGrade, "", &workflow.StartProcessInstanceRequest{
 			ProcessCode: &BusinessDowngradeRequestProcessCode,
 			FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
 				{
@@ -932,7 +932,7 @@ func (p *businessService) ConvertToReserve(req *model.BusinessToReserveReq) erro
 
 		// OMS项目转储备 审批
 		bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
-		_, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectToReserve, &workflow.StartProcessInstanceRequest{
+		_, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectToReserve, "", &workflow.StartProcessInstanceRequest{
 			ProcessCode: &ConvertToReserveRequestProcessCode,
 			FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
 				{

+ 4 - 3
opms_parent/app/service/workflow/work_flow.go

@@ -49,7 +49,7 @@ func (s *workflowService) GetProcessInstanceDetail(instId string) (*workflow.Que
 // ProcessCode = utils.String("每种审批对应固定的code")
 // bizType:业务类型(10领用20项目创建30合同创建
 // 详情参照文档:https://open.dingtalk.com/document/orgapp/create-an-approval-instance
-func (s *workflowService) StartProcessInstance(bizCode, bizType string, flow *workflow.StartProcessInstanceRequest) (insertId int64, err error) {
+func (s *workflowService) StartProcessInstance(bizCode, bizType, remark string, flow *workflow.StartProcessInstanceRequest) (insertId int64, err error) {
 	// 参数调整
 	if flow.OriginatorUserId == nil {
 		flow.OriginatorUserId = utils.String(s.GetCxtUserDingtalkUid())
@@ -66,7 +66,7 @@ func (s *workflowService) StartProcessInstance(bizCode, bizType string, flow *wo
 		return 0, err
 	}
 
-	return s.saveWorkflowInstance(bizCode, bizType, resp.InstanceId)
+	return s.saveWorkflowInstance(bizCode, bizType, remark, resp.InstanceId)
 }
 
 // RevokeProcessInstance 撤销审批实例(钉钉接口)
@@ -83,7 +83,7 @@ func (s *workflowService) RevokeProcessInstance(instId, remark string) (string,
 }
 
 // 将审批实例同步到数据库中
-func (s *workflowService) saveWorkflowInstance(bizCode, bizType, instanceId string) (insertId int64, err error) {
+func (s *workflowService) saveWorkflowInstance(bizCode, bizType, remark, instanceId string) (insertId int64, err error) {
 	now := gtime.Now()
 
 	// 构造基础数据
@@ -93,6 +93,7 @@ func (s *workflowService) saveWorkflowInstance(bizCode, bizType, instanceId stri
 	instance.CurrentNode = "create"
 	instance.CurrentNodeTime = now.Format("Y-m-d H:i:s")
 	instance.ProcessInstId = instanceId
+	instance.Remark = remark
 	// 填充创建信息
 	service.SetCreatedInfo(&instance, s.GetCxtUserId(), s.GetCxtUserName())
 

+ 1 - 0
opms_parent/main.go

@@ -54,6 +54,7 @@ func main() {
 	s.RegisterName("WorkOrder", new(work.WorkOrderHandler), "")
 	s.RegisterName("Schedule", new(plat.ScheduleHeader), "")
 	s.RegisterName("PlatWorkflow", new(workflow.PlatWorkflowHandler), "")
+	s.RegisterName("DingUpload", new(dingtalk.DingUploadHandler), "")
 
 	// 钉钉回调接口
 	s.RegisterName("DingEvent", new(dingtalk.DingHandler), "")

+ 1 - 1
opms_parent/schema/contract.sql

@@ -6,7 +6,7 @@ CREATE TABLE `ctr_contract` (
     `cust_name` varchar(90) NOT NULL COMMENT '客户名称',
     `nbo_id` int(11) NOT NULL COMMENT '关联项目',
     `nbo_name` varchar(90) NOT NULL COMMENT '项目名称',
-    `appro_status` varchar(4) NOT NULL COMMENT '审批状态',
+    `appro_status` varchar(4) NOT NULL COMMENT '审核状态 10 待提交审核 20 待审核 30 审核已同意 40 审核已拒绝 50 审核已撤销',
     `contract_type` varchar(255) NOT NULL COMMENT '合同类型',
     `contract_amount` decimal(24, 6) NOT NULL COMMENT '合同金额',
     `invoice_amount` decimal(24, 6) NOT NULL COMMENT '已开票金额',

+ 2 - 0
opms_parent/schema/tmp.sql

@@ -10,3 +10,5 @@ alter table ctr_contract_invoice modify `appro_status` varchar(4) DEFAULT NULL C
 
 alter table ctr_contract add `signatory_type` varchar(255) DEFAULT NULL COMMENT '签订单位类型 10 终端用户 20 经销商 30 代理商' after signatory_name;
 alter table ctr_contract modify `incharge_name` varchar(90) COMMENT '负责人(销售工程师)';
+
+alter table ctr_contract modify `appro_status` varchar(4) NOT NULL COMMENT '审核状态 10 待提交审核 20 待审核 30 审核已同意 40 审核已拒绝 50 审核已撤销',

+ 8 - 0
opms_parent/swaggerui/swagger.go

@@ -227,6 +227,9 @@ func main() {
 			if os.IsNotExist(err) {
 				continue
 			}
+			if f.Name() == ".DS_Store" {
+				continue
+			}
 			if info.IsDir() {
 				toload = append(toload, fmt.Sprintf("%s/%s/%s/internal", modname, d, f.Name()))
 			}
@@ -619,6 +622,11 @@ func buildFromType(tpe types.Type, declFile *ast.File, desc string) (error, *Swa
 			Type:        "object",
 			Description: desc,
 		}
+	case *types.Map:
+		return nil, &SwaggerModel{
+			Type:        "object",
+			Description: desc,
+		}
 
 	default:
 		panic(fmt.Sprintf("WARNING: can't determine refined type %s (%T)", titpe.String(), titpe))