瀏覽代碼

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

liuyaqi 2 年之前
父節點
當前提交
6275dd47b5
共有 37 個文件被更改,包括 2199 次插入149 次删除
  1. 36 0
      opms_parent/app/dao/work/deliver_progress_product.go
  2. 3 0
      opms_parent/app/dao/work/internal/deliver_order_imp_progress.go
  3. 3 0
      opms_parent/app/dao/work/internal/deliver_order_product.go
  4. 851 0
      opms_parent/app/dao/work/internal/deliver_progress_product.go
  5. 2 2
      opms_parent/app/handler/base/region.go
  6. 44 0
      opms_parent/app/handler/contract/report.go
  7. 19 0
      opms_parent/app/handler/dingtalk/ding_event.go
  8. 28 0
      opms_parent/app/handler/proj/report.go
  9. 94 0
      opms_parent/app/handler/sysreport/work_order_report.go
  10. 14 0
      opms_parent/app/handler/work/deliver_order.go
  11. 4 0
      opms_parent/app/model/base/base_sales_region.go
  12. 4 4
      opms_parent/app/model/contract/ctr_contract.go
  13. 5 0
      opms_parent/app/model/contract/report.go
  14. 5 0
      opms_parent/app/model/proj/report.go
  15. 28 0
      opms_parent/app/model/sys_report/sys_report.go
  16. 19 4
      opms_parent/app/model/work/deliver_order.go
  17. 8 7
      opms_parent/app/model/work/deliver_order_imp_progress.go
  18. 14 0
      opms_parent/app/model/work/deliver_progress_product.go
  19. 1 0
      opms_parent/app/model/work/internal/deliver_order_imp_progress.go
  20. 1 0
      opms_parent/app/model/work/internal/deliver_order_product.go
  21. 35 0
      opms_parent/app/model/work/internal/deliver_progress_product.go
  22. 2 1
      opms_parent/app/model/work/work_order.go
  23. 18 17
      opms_parent/app/model/workflow/plat_workflow.go
  24. 40 0
      opms_parent/app/service/base.go
  25. 2 2
      opms_parent/app/service/base/base_product.go
  26. 37 7
      opms_parent/app/service/base/base_sales_region.go
  27. 5 5
      opms_parent/app/service/contract/ctr_contract.go
  28. 200 0
      opms_parent/app/service/contract/report.go
  29. 2 2
      opms_parent/app/service/home/report.go
  30. 3 3
      opms_parent/app/service/plat/plat_task_cron.go
  31. 114 0
      opms_parent/app/service/proj/report.go
  32. 155 0
      opms_parent/app/service/sys_report/work_order.go
  33. 253 36
      opms_parent/app/service/work/deliver_order.go
  34. 2 2
      opms_parent/app/service/work/deliver_order_cron.go
  35. 139 57
      opms_parent/app/service/work/deliver_order_progress.go
  36. 6 0
      opms_parent/app/service/work/work_order.go
  37. 3 0
      opms_parent/main.go

+ 36 - 0
opms_parent/app/dao/work/deliver_progress_product.go

@@ -0,0 +1,36 @@
+// ============================================================================
+// This is auto-generated by gf cli tool only once. Fill this file as you wish.
+// ============================================================================
+
+package work
+
+import (
+	"dashoo.cn/micro/app/dao/work/internal"
+)
+
+// deliverProgressProductDao 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 deliverProgressProductDao struct {
+	internal.DeliverProgressProductDao
+}
+
+var (
+	// DeliverProgressProduct is globally public accessible object for table deliver_progress_product operations.
+	DeliverProgressProduct = deliverProgressProductDao{
+		internal.DeliverProgressProduct,
+	}
+)
+
+type DeliverProgressProductDao struct {
+	internal.DeliverProgressProductDao
+}
+
+func NewDeliverProgressProductDao(tenant string) *DeliverProgressProductDao {
+	dao := internal.NewDeliverProgressProductDao(tenant)
+	return &DeliverProgressProductDao{
+		dao,
+	}
+}
+
+// Fill with you ideas below.

+ 3 - 0
opms_parent/app/dao/work/internal/deliver_order_imp_progress.go

@@ -33,6 +33,7 @@ type deliverOrderImpProgressColumns struct {
 	Id                   string // 主键
 	DeliverOrderId       string // 关联交付订单ID
 	PlanId               string // 关联实施计划
+	DeliverProgressId    string // 关联发货任务单Id
 	ProgressTitle        string // 任务标题
 	ProgressContext      string // 任务内容
 	StartDate            string // 开始时间
@@ -78,6 +79,7 @@ var (
 			Id:                   "id",
 			DeliverOrderId:       "deliver_order_id",
 			PlanId:               "plan_id",
+			DeliverProgressId:    "deliver_progress_id",
 			ProgressTitle:        "progress_title",
 			ProgressContext:      "progress_context",
 			StartDate:            "start_date",
@@ -125,6 +127,7 @@ func NewDeliverOrderImpProgressDao(tenant string) DeliverOrderImpProgressDao {
 			Id:                   "id",
 			DeliverOrderId:       "deliver_order_id",
 			PlanId:               "plan_id",
+			DeliverProgressId:    "deliver_progress_id",
 			ProgressTitle:        "progress_title",
 			ProgressContext:      "progress_context",
 			StartDate:            "start_date",

+ 3 - 0
opms_parent/app/dao/work/internal/deliver_order_product.go

@@ -36,6 +36,7 @@ type deliverOrderProductColumns struct {
 	ProductName        string // 产品名称
 	ProductType        string // 产品类型
 	ProductNum         string // 产品数量
+	CompleteNum        string // 已完成数量
 	IsDeliver          string // 10 未开始;20 已操作
 	IsComplete         string // 10 未完成;20 组装或外购
 	IsInstall          string // 10 未开始;20 安装部署完成
@@ -66,6 +67,7 @@ var (
 			ProductName:        "product_name",
 			ProductType:        "product_type",
 			ProductNum:         "product_num",
+			CompleteNum:        "complete_num",
 			IsDeliver:          "is_deliver",
 			IsComplete:         "is_complete",
 			IsInstall:          "is_install",
@@ -98,6 +100,7 @@ func NewDeliverOrderProductDao(tenant string) DeliverOrderProductDao {
 			ProductName:        "product_name",
 			ProductType:        "product_type",
 			ProductNum:         "product_num",
+			CompleteNum:        "complete_num",
 			IsDeliver:          "is_deliver",
 			IsComplete:         "is_complete",
 			IsInstall:          "is_install",

+ 851 - 0
opms_parent/app/dao/work/internal/deliver_progress_product.go

@@ -0,0 +1,851 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"context"
+	"database/sql"
+	"fmt"
+	"github.com/gogf/gf/container/garray"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/frame/gmvc"
+	"github.com/gogf/gf/util/gconv"
+	"strings"
+	"time"
+
+	model "dashoo.cn/micro/app/model/work"
+)
+
+// DeliverProgressProductDao is the manager for logic model data accessing and custom defined data operations functions management.
+type DeliverProgressProductDao struct {
+	gmvc.M                                // M is the core and embedded struct that inherits all chaining operations from gdb.Model.
+	C       deliverProgressProductColumns // C is the short type for Columns, which contains all the column names of Table for convenient usage.
+	DB      gdb.DB                        // DB is the raw underlying database management object.
+	Table   string                        // Table is the underlying table name of the DAO.
+	TableAs string                        // TableAs is the underlying table alias name of the DAO.
+}
+
+// DeliverProgressProductColumns defines and stores column names for table deliver_progress_product.
+type deliverProgressProductColumns struct {
+	Id                 string // 主键
+	DeliverOrderId     string // 关联交付订单ID
+	DeliverProgressId  string // 关联的发货任务单Id
+	AssembleProgressId string // 关联的组装任务单Id
+	InstallProgressId  string // 关联的部署安装单
+	ProductId          string // 关联产品Id
+	ProductCode        string // 产品编码
+	ProductName        string // 产品名称
+	ProductType        string // 产品类型
+	ProductNum         string // 产品数量
+	IsDeliver          string // 10 未开始;20 已操作
+	IsComplete         string // 10 未完成;20 组装或外购完成
+	IsInstall          string // 10 未开始;20 安装部署完成
+	OperateType        string // 获取方式:组装;外购
+	Remark             string // 备注
+	CreatedBy          string // 创建者
+	CreatedName        string // 创建人
+	CreatedTime        string // 创建时间
+	UpdatedBy          string // 更新者
+	UpdatedName        string // 更新人
+	UpdatedTime        string // 更新时间
+	DeletedTime        string // 删除时间
+}
+
+var (
+	// DeliverProgressProduct is globally public accessible object for table deliver_progress_product operations.
+	DeliverProgressProduct = DeliverProgressProductDao{
+		M:     g.DB("default").Model("deliver_progress_product").Safe(),
+		DB:    g.DB("default"),
+		Table: "deliver_progress_product",
+		C: deliverProgressProductColumns{
+			Id:                 "id",
+			DeliverOrderId:     "deliver_order_id",
+			DeliverProgressId:  "deliver_progress_id",
+			AssembleProgressId: "assemble_progress_id",
+			InstallProgressId:  "install_progress_id",
+			ProductId:          "product_id",
+			ProductCode:        "product_code",
+			ProductName:        "product_name",
+			ProductType:        "product_type",
+			ProductNum:         "product_num",
+			IsDeliver:          "is_deliver",
+			IsComplete:         "is_complete",
+			IsInstall:          "is_install",
+			OperateType:        "operate_type",
+			Remark:             "remark",
+			CreatedBy:          "created_by",
+			CreatedName:        "created_name",
+			CreatedTime:        "created_time",
+			UpdatedBy:          "updated_by",
+			UpdatedName:        "updated_name",
+			UpdatedTime:        "updated_time",
+			DeletedTime:        "deleted_time",
+		},
+	}
+)
+
+func NewDeliverProgressProductDao(tenant string) DeliverProgressProductDao {
+	var dao DeliverProgressProductDao
+	dao = DeliverProgressProductDao{
+		M:     g.DB(tenant).Model("deliver_progress_product").Safe(),
+		DB:    g.DB(tenant),
+		Table: "deliver_progress_product",
+		C: deliverProgressProductColumns{
+			Id:                 "id",
+			DeliverOrderId:     "deliver_order_id",
+			DeliverProgressId:  "deliver_progress_id",
+			AssembleProgressId: "assemble_progress_id",
+			InstallProgressId:  "install_progress_id",
+			ProductId:          "product_id",
+			ProductCode:        "product_code",
+			ProductName:        "product_name",
+			ProductType:        "product_type",
+			ProductNum:         "product_num",
+			IsDeliver:          "is_deliver",
+			IsComplete:         "is_complete",
+			IsInstall:          "is_install",
+			OperateType:        "operate_type",
+			Remark:             "remark",
+			CreatedBy:          "created_by",
+			CreatedName:        "created_name",
+			CreatedTime:        "created_time",
+			UpdatedBy:          "updated_by",
+			UpdatedName:        "updated_name",
+			UpdatedTime:        "updated_time",
+			DeletedTime:        "deleted_time",
+		},
+	}
+	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 *DeliverProgressProductDao) Ctx(ctx context.Context) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Ctx(ctx), Table: d.Table, TableAs: d.TableAs}
+}
+
+// GetCtx returns the context for current Model.
+// It returns "context.Background() i"s there's no context previously set.
+func (d *DeliverProgressProductDao) GetCtx() context.Context {
+	return d.M.GetCtx()
+}
+
+// As sets an alias name for current table.
+func (d *DeliverProgressProductDao) As(as string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.As(as), Table: d.Table, TableAs: as}
+}
+
+// TX sets the transaction for current operation.
+func (d *DeliverProgressProductDao) TX(tx *gdb.TX) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.TX(tx), Table: d.Table, TableAs: d.TableAs}
+}
+
+// Master marks the following operation on master node.
+func (d *DeliverProgressProductDao) Master() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Master(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// Slave marks the following operation on slave node.
+// Note that it makes sense only if there's any slave node configured.
+func (d *DeliverProgressProductDao) Slave() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Slave(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// Args sets custom arguments for model operation.
+func (d *DeliverProgressProductDao) Args(args ...interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Args(args...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) Handler(handlers ...gdb.ModelHandler) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Handler(handlers...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) LeftJoin(table ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.LeftJoin(table...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) RightJoin(table ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.RightJoin(table...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) InnerJoin(table ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.InnerJoin(table...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) Fields(fieldNamesOrMapStruct ...interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Fields(fieldNamesOrMapStruct...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// FieldCount formats and appends commonly used field "COUNT(column)" to the select fields of model.
+func (d *DeliverProgressProductDao) FieldCount(column string, as ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.FieldCount(column, as...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// FieldSum formats and appends commonly used field "SUM(column)" to the select fields of model.
+func (d *DeliverProgressProductDao) FieldSum(column string, as ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.FieldSum(column, as...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// FieldMin formats and appends commonly used field "MIN(column)" to the select fields of model.
+func (d *DeliverProgressProductDao) FieldMin(column string, as ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.FieldMin(column, as...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// FieldMax formats and appends commonly used field "MAX(column)" to the select fields of model.
+func (d *DeliverProgressProductDao) FieldMax(column string, as ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.FieldMax(column, as...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// FieldAvg formats and appends commonly used field "AVG(column)" to the select fields of model.
+func (d *DeliverProgressProductDao) FieldAvg(column string, as ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.FieldAvg(column, as...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// Option adds extra operation option for the model.
+// Deprecated, use separate operations instead.
+func (d *DeliverProgressProductDao) Option(option int) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Option(option), Table: d.Table, TableAs: d.TableAs}
+}
+
+// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers
+// the data and where attributes for empty values.
+func (d *DeliverProgressProductDao) OmitEmpty() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.OmitEmpty(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// OmitEmptyWhere sets optionOmitEmptyWhere option for the model, which automatically filers
+// the Where/Having parameters for "empty" values.
+func (d *DeliverProgressProductDao) OmitEmptyWhere() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.OmitEmptyWhere(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// OmitEmptyData sets optionOmitEmptyData option for the model, which automatically filers
+// the Data parameters for "empty" values.
+func (d *DeliverProgressProductDao) OmitEmptyData() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.OmitEmptyData(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// OmitNil sets optionOmitNil option for the model, which automatically filers
+// the data and where parameters for "nil" values.
+func (d *DeliverProgressProductDao) OmitNil() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.OmitNil(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// OmitNilWhere sets optionOmitNilWhere option for the model, which automatically filers
+// the Where/Having parameters for "nil" values.
+func (d *DeliverProgressProductDao) OmitNilWhere() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.OmitNilWhere(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// OmitNilData sets optionOmitNilData option for the model, which automatically filers
+// the Data parameters for "nil" values.
+func (d *DeliverProgressProductDao) OmitNilData() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.OmitNilData(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) Filter() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Filter(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) Where(where interface{}, args ...interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Where(where, args...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) WherePri(where interface{}, args ...interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WherePri(where, args...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) Having(having interface{}, args ...interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Having(having, args...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) Wheref(format string, args ...interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Wheref(format, args...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereLT builds "column < value" statement.
+func (d *DeliverProgressProductDao) WhereLT(column string, value interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereLT(column, value), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereLTE builds "column <= value" statement.
+func (d *DeliverProgressProductDao) WhereLTE(column string, value interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereLTE(column, value), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereGT builds "column > value" statement.
+func (d *DeliverProgressProductDao) WhereGT(column string, value interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereGT(column, value), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereGTE builds "column >= value" statement.
+func (d *DeliverProgressProductDao) WhereGTE(column string, value interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereGTE(column, value), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereBetween builds "column BETWEEN min AND max" statement.
+func (d *DeliverProgressProductDao) WhereBetween(column string, min, max interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereBetween(column, min, max), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereLike builds "column LIKE like" statement.
+func (d *DeliverProgressProductDao) WhereLike(column string, like interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereLike(column, like), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereIn builds "column IN (in)" statement.
+func (d *DeliverProgressProductDao) WhereIn(column string, in interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereIn(column, in), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereNull builds "columns[0] IS NULL AND columns[1] IS NULL ..." statement.
+func (d *DeliverProgressProductDao) WhereNull(columns ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereNull(columns...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereNotBetween builds "column NOT BETWEEN min AND max" statement.
+func (d *DeliverProgressProductDao) WhereNotBetween(column string, min, max interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereNotBetween(column, min, max), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereNotLike builds "column NOT LIKE like" statement.
+func (d *DeliverProgressProductDao) WhereNotLike(column string, like interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereNotLike(column, like), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereNot builds "column != value" statement.
+func (d *DeliverProgressProductDao) WhereNot(column string, value interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereNot(column, value), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereNotIn builds "column NOT IN (in)" statement.
+func (d *DeliverProgressProductDao) WhereNotIn(column string, in interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereNotIn(column, in), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereNotNull builds "columns[0] IS NOT NULL AND columns[1] IS NOT NULL ..." statement.
+func (d *DeliverProgressProductDao) WhereNotNull(columns ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereNotNull(columns...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOr adds "OR" condition to the where statement.
+func (d *DeliverProgressProductDao) WhereOr(where interface{}, args ...interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOr(where, args...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOrf builds "OR" condition string using fmt.Sprintf and arguments.
+func (d *DeliverProgressProductDao) WhereOrf(format string, args ...interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOrf(format, args...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOrLT builds "column < value" statement in "OR" conditions..
+func (d *DeliverProgressProductDao) WhereOrLT(column string, value interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOrLT(column, value), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOrLTE builds "column <= value" statement in "OR" conditions..
+func (d *DeliverProgressProductDao) WhereOrLTE(column string, value interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOrLTE(column, value), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOrGT builds "column > value" statement in "OR" conditions..
+func (d *DeliverProgressProductDao) WhereOrGT(column string, value interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOrGT(column, value), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOrGTE builds "column >= value" statement in "OR" conditions..
+func (d *DeliverProgressProductDao) WhereOrGTE(column string, value interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOrGTE(column, value), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOrBetween builds "column BETWEEN min AND max" statement in "OR" conditions.
+func (d *DeliverProgressProductDao) WhereOrBetween(column string, min, max interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOrBetween(column, min, max), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOrLike builds "column LIKE like" statement in "OR" conditions.
+func (d *DeliverProgressProductDao) WhereOrLike(column string, like interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOrLike(column, like), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOrIn builds "column IN (in)" statement in "OR" conditions.
+func (d *DeliverProgressProductDao) WhereOrIn(column string, in interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOrIn(column, in), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOrNull builds "columns[0] IS NULL OR columns[1] IS NULL ..." statement in "OR" conditions.
+func (d *DeliverProgressProductDao) WhereOrNull(columns ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOrNull(columns...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOrNotBetween builds "column NOT BETWEEN min AND max" statement in "OR" conditions.
+func (d *DeliverProgressProductDao) WhereOrNotBetween(column string, min, max interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOrNotBetween(column, min, max), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOrNotLike builds "column NOT LIKE like" statement in "OR" conditions.
+func (d *DeliverProgressProductDao) WhereOrNotLike(column string, like interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOrNotLike(column, like), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOrNotIn builds "column NOT IN (in)" statement.
+func (d *DeliverProgressProductDao) WhereOrNotIn(column string, in interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOrNotIn(column, in), Table: d.Table, TableAs: d.TableAs}
+}
+
+// WhereOrNotNull builds "columns[0] IS NOT NULL OR columns[1] IS NOT NULL ..." statement in "OR" conditions.
+func (d *DeliverProgressProductDao) WhereOrNotNull(columns ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.WhereOrNotNull(columns...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// Group sets the "GROUP BY" statement for the model.
+func (d *DeliverProgressProductDao) Group(groupBy ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Group(groupBy...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// And adds "AND" condition to the where statement.
+// Deprecated, use Where instead.
+func (d *DeliverProgressProductDao) And(where interface{}, args ...interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.And(where, args...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// Or adds "OR" condition to the where statement.
+// Deprecated, use WhereOr instead.
+func (d *DeliverProgressProductDao) Or(where interface{}, args ...interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Or(where, args...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// GroupBy sets the "GROUP BY" statement for the model.
+func (d *DeliverProgressProductDao) GroupBy(groupBy string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Group(groupBy), Table: d.Table, TableAs: d.TableAs}
+}
+
+// Order sets the "ORDER BY" statement for the model.
+func (d *DeliverProgressProductDao) Order(orderBy ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Order(orderBy...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// OrderAsc sets the "ORDER BY xxx ASC" statement for the model.
+func (d *DeliverProgressProductDao) OrderAsc(column string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.OrderAsc(column), Table: d.Table, TableAs: d.TableAs}
+}
+
+// OrderDesc sets the "ORDER BY xxx DESC" statement for the model.
+func (d *DeliverProgressProductDao) OrderDesc(column string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.OrderDesc(column), Table: d.Table, TableAs: d.TableAs}
+}
+
+// OrderRandom sets the "ORDER BY RANDOM()" statement for the model.
+func (d *DeliverProgressProductDao) OrderRandom() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.OrderRandom(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// OrderBy is alias of Model.Order.
+// See Model.Order.
+// Deprecated, use Order instead.
+func (d *DeliverProgressProductDao) OrderBy(orderBy string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Order(orderBy), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) Limit(limit ...int) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Limit(limit...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// Offset sets the "OFFSET" statement for the model.
+// It only makes sense for some databases like SQLServer, PostgreSQL, etc.
+func (d *DeliverProgressProductDao) Offset(offset int) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Offset(offset), Table: d.Table, TableAs: d.TableAs}
+}
+
+// Distinct forces the query to only return distinct results.
+func (d *DeliverProgressProductDao) Distinct() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Distinct(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) Page(page, limit int) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Page(page, limit), Table: d.Table, TableAs: d.TableAs}
+}
+
+// Batch sets the batch operation number for the model.
+func (d *DeliverProgressProductDao) Batch(batch int) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Batch(batch), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) Cache(duration time.Duration, name ...string) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Cache(duration, name...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// 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 *DeliverProgressProductDao) Data(data ...interface{}) *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Data(data...), Table: d.Table, TableAs: d.TableAs}
+}
+
+// All does "SELECT FROM ..." statement for the model.
+// It retrieves the records from table and returns the result as []*model.DeliverProgressProduct.
+// 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 *DeliverProgressProductDao) All(where ...interface{}) ([]*model.DeliverProgressProduct, error) {
+	all, err := d.M.All(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*model.DeliverProgressProduct
+	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.DeliverProgressProduct.
+// 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 *DeliverProgressProductDao) One(where ...interface{}) (*model.DeliverProgressProduct, error) {
+	one, err := d.M.One(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *model.DeliverProgressProduct
+	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 *DeliverProgressProductDao) FindOne(where ...interface{}) (*model.DeliverProgressProduct, error) {
+	one, err := d.M.FindOne(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *model.DeliverProgressProduct
+	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 *DeliverProgressProductDao) FindAll(where ...interface{}) ([]*model.DeliverProgressProduct, error) {
+	all, err := d.M.FindAll(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*model.DeliverProgressProduct
+	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 *DeliverProgressProductDao) 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 *DeliverProgressProductDao) 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 *DeliverProgressProductDao) Scan(pointer interface{}, where ...interface{}) error {
+	return d.M.Scan(pointer, where...)
+}
+
+// Chunk iterates the table with given size and callback function.
+func (d *DeliverProgressProductDao) Chunk(limit int, callback func(entities []*model.DeliverProgressProduct, err error) bool) {
+	d.M.Chunk(limit, func(result gdb.Result, err error) bool {
+		var entities []*model.DeliverProgressProduct
+		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 *DeliverProgressProductDao) LockUpdate() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.LockUpdate(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// LockShared sets the lock in share mode for current operation.
+func (d *DeliverProgressProductDao) LockShared() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.LockShared(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// Unscoped enables/disables the soft deleting feature.
+func (d *DeliverProgressProductDao) Unscoped() *DeliverProgressProductDao {
+	return &DeliverProgressProductDao{M: d.M.Unscoped(), Table: d.Table, TableAs: d.TableAs}
+}
+
+// DataScope enables the DataScope feature.
+func (d *DeliverProgressProductDao) DataScope(ctx context.Context, args ...interface{}) *DeliverProgressProductDao {
+	cs := ctx.Value("contextService")
+	dataScope := gconv.Map(gconv.String(gconv.Map(cs)["dataScope"]))
+	if dataScope != nil {
+		// 销售工程师判断
+		var salesEngineerFlag bool
+		if roles, ok := dataScope["roles"]; ok {
+			arr := garray.NewArrayFrom(roles.([]interface{}), true)
+			if arr.Len() == 1 && arr.Contains("SalesEngineer") {
+				salesEngineerFlag = true
+			}
+		}
+		userIds, ok := dataScope["userIds"]
+		specialFlag, userCols, orColsMap := d.checkColumnsName(dataScope, args...)
+
+		var orColumns []string
+		var orValues []interface{}
+		if ok && userIds != "-1" {
+			for _, column := range userCols {
+				if ok, _ := d.M.HasField(column); ok || specialFlag {
+					orColumns = append(orColumns, column+" IN (?) ")
+					orValues = append(orValues, userIds)
+				}
+			}
+		}
+		for col, params := range orColsMap {
+			if ok, _ := d.M.HasField(col); ok || specialFlag {
+				orColumns = append(orColumns, fmt.Sprintf(" ( %s IN (?) )", col))
+				orValues = append(orValues, params)
+			}
+		}
+
+		// 销售工程师权限加成
+		if !salesEngineerFlag {
+			var andColumns []string
+			var andValues []interface{}
+			for col, params := range dataScope {
+				if ok, _ := d.M.HasField(col); ok || specialFlag {
+					andColumns = append(andColumns, fmt.Sprintf(" ( %s IN (?) )", col))
+					andValues = append(andValues, params)
+				}
+			}
+			if len(andColumns) > 0 {
+				andWhereSql := strings.Join(andColumns, " AND ")
+				orColumns = append(orColumns, "("+andWhereSql+")")
+				orValues = append(orValues, andValues...)
+			}
+		}
+
+		whereSql := strings.Join(orColumns, " OR ")
+		return &DeliverProgressProductDao{M: d.M.Where(whereSql, orValues...).Ctx(ctx), Table: d.Table, TableAs: d.TableAs}
+	}
+	return d
+}
+
+// args 1、字段
+// args 2、字段、表名
+// args 3、字段对应关系
+func (d *DeliverProgressProductDao) checkColumnsName(dataScope map[string]interface{}, args ...interface{}) (bool, []string, map[string]interface{}) {
+	var userCols []string
+	tableAs, specialFlag := "", false
+	orColsMap, colsContrast := map[string]interface{}{}, map[string]interface{}{}
+
+	if d.TableAs != "" && len(args) <= 1 {
+		tableAs = d.TableAs + "."
+	}
+	if len(args) > 1 {
+		specialFlag = true
+		if val, ok := args[1].(string); ok {
+			tableAs = val + "."
+		}
+	}
+	if len(args) > 0 {
+		userCols = []string{"created_by"}
+		if column, ok := args[0].(string); ok {
+			userCols = []string{tableAs + column}
+		}
+		if cols, ok := args[0].([]string); ok {
+			for _, v := range cols {
+				userCols = append(userCols, tableAs+v)
+			}
+		}
+		if val, ok := args[0].(map[string]interface{}); ok {
+			specialFlag = true
+			colsContrast = val
+			if orcols, ok := val["orcols"]; ok {
+				if col, ok := orcols.(string); ok && gconv.String(val[col]) != "" {
+					orColsMap[col] = val[col]
+					delete(colsContrast, col)
+				}
+				if cols, ok := orcols.([]string); ok {
+					for _, col := range cols {
+						if gconv.String(val[col]) == "" {
+							continue
+						}
+						orColsMap[col] = val[col]
+						delete(colsContrast, col)
+					}
+				}
+			}
+			delete(colsContrast, "orcols")
+		}
+	}
+	bigColumns := "is_big"
+	if isBig, ok := dataScope[bigColumns]; ok {
+		if bigCol, ok := colsContrast[bigColumns]; ok {
+			orColsMap[bigCol.(string)] = isBig
+			delete(colsContrast, bigCol.(string))
+		} else {
+			if ok, _ := d.M.HasField(bigColumns); ok && specialFlag {
+				orColsMap[tableAs+bigColumns] = isBig
+			}
+		}
+	}
+
+	delete(dataScope, "userIds")
+	delete(dataScope, "roles")
+	delete(dataScope, "posts")
+	delete(dataScope, bigColumns)
+	if len(colsContrast) > 0 {
+		for k, v := range dataScope {
+			if data, ok := colsContrast[k]; ok {
+				dataScope[data.(string)] = v
+			}
+			delete(dataScope, k)
+			delete(colsContrast, k)
+		}
+		for k, v := range colsContrast {
+			dataScope[k] = v
+		}
+	}
+	return specialFlag, userCols, orColsMap
+}

+ 2 - 2
opms_parent/app/handler/base/region.go

@@ -42,12 +42,12 @@ func (r *RegionHandler) GetRegionDetailList(ctx context.Context, req *model.SecB
 }
 
 // GetRegionTree 获取大区及下属地区
-func (p *RegionHandler) GetRegionTree(ctx context.Context, null, rsp *comm_def.CommonMsg) error {
+func (p *RegionHandler) GetRegionTree(ctx context.Context, req *model.RegionTreeReq, rsp *comm_def.CommonMsg) error {
 	regionServer, err := server.NewSalesRegionService(ctx)
 	if err != nil {
 		return err
 	}
-	list, err := regionServer.GetRegionTree()
+	list, err := regionServer.GetRegionTree(req)
 	if err != nil {
 		return err
 	}

+ 44 - 0
opms_parent/app/handler/contract/report.go

@@ -0,0 +1,44 @@
+package contract
+
+import (
+	"context"
+
+	"dashoo.cn/common_definition/comm_def"
+	model "dashoo.cn/micro/app/model/contract"
+	service "dashoo.cn/micro/app/service/contract"
+	"github.com/gogf/gf/frame/g"
+)
+
+type ContractReportHandler struct{}
+
+// QueryCollectionNum 业绩指标-回款金额
+func (c *ContractReportHandler) QueryCollectionNum(ctx context.Context, req *model.QueryNumReq, rsp *comm_def.CommonMsg) error {
+	g.Log().Infof("ContractReport.QueryCollectionNum request %#v ", *req)
+	s, err := service.NewContractReportService(ctx)
+	if err != nil {
+		return err
+	}
+	data, err := s.QueryCollectionNum(req.Date)
+	if err != nil {
+		return err
+	}
+
+	rsp.Data = data
+	return nil
+}
+
+// QueryContractNum 业绩指标-签约合同金额
+func (c *ContractReportHandler) QueryContractNum(ctx context.Context, req *model.QueryNumReq, rsp *comm_def.CommonMsg) error {
+	g.Log().Infof("ContractReport.QueryContractNum request %#v ", *req)
+	s, err := service.NewContractReportService(ctx)
+	if err != nil {
+		return err
+	}
+	data, err := s.QueryContractNum(req.Date)
+	if err != nil {
+		return err
+	}
+
+	rsp.Data = data
+	return nil
+}

+ 19 - 0
opms_parent/app/handler/dingtalk/ding_event.go

@@ -260,6 +260,25 @@ func (h *DingHandler) handleBpmsInstanceChange(msg *message.MixMessage, ctx *din
 			return err.Error()
 		}
 		return "success"
+	case model.DeliverOrderCreate:
+		if msg.ProcessType == "finish" || msg.ProcessType == "terminate" {
+			srv, err := workService.NewDeliverOrderService(ctx.SubsMessage.Ctx)
+			if err != nil {
+				glog.Error(err)
+				return err.Error()
+			}
+			err = srv.DeliverOrderNotify(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.ProjectCreate:
 		if msg.ProcessType == "finish" || msg.ProcessType == "terminate" {
 			srv, err := projService.NewBusinessService(ctx.SubsMessage.Ctx)

+ 28 - 0
opms_parent/app/handler/proj/report.go

@@ -0,0 +1,28 @@
+package base
+
+import (
+	"context"
+
+	"dashoo.cn/common_definition/comm_def"
+	model "dashoo.cn/micro/app/model/proj"
+	service "dashoo.cn/micro/app/service/proj"
+	"github.com/gogf/gf/frame/g"
+)
+
+type BusinessReportHandler struct{}
+
+// QueryBusinessNum 业绩指标-当月新增项目
+func (c *BusinessReportHandler) QueryBusinessNum(ctx context.Context, req *model.QueryNumReq, rsp *comm_def.CommonMsg) error {
+	g.Log().Infof("ContractReport.QueryBusinessNum request %#v ", *req)
+	s, err := service.NewBusinessReportService(ctx)
+	if err != nil {
+		return err
+	}
+	data, err := s.QueryBusinessNum(req.Date)
+	if err != nil {
+		return err
+	}
+
+	rsp.Data = data
+	return nil
+}

+ 94 - 0
opms_parent/app/handler/sysreport/work_order_report.go

@@ -0,0 +1,94 @@
+package sysreport
+
+import (
+	"context"
+	"dashoo.cn/common_definition/comm_def"
+	"dashoo.cn/micro/app/model/sys_report"
+	service "dashoo.cn/micro/app/service/sys_report"
+	"github.com/gogf/gf/util/gvalid"
+)
+
+type WorkOrderReportHandle struct {
+}
+
+// Swagger:WorkOrderReport  销售工单统计报表
+func (s *WorkOrderReportHandle) GetSaleWorkOrderReportList(ctx context.Context, req *sys_report.SearchPunchRecordsData, rsp *comm_def.CommonMsg) error {
+	svc, err := service.NewWorkOrderService(ctx)
+	if err != nil {
+		return err
+	}
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+
+	resp, err := svc.GetSaleWorkOrderReportList(req.Month)
+	if err != nil {
+		return err
+	}
+	rsp.Code = 200
+	rsp.Msg = "查询成功"
+	rsp.Data = resp
+
+	return nil
+}
+
+//  Swagger:WorkOrderReport 产品线工单统计报表
+func (s *WorkOrderReportHandle) GetProductWorkOrderReportList(ctx context.Context, req *sys_report.SearchPunchRecordsData, rsp *comm_def.CommonMsg) error {
+	svc, err := service.NewWorkOrderService(ctx)
+	if err != nil {
+		return err
+	}
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+
+	resp, err := svc.GetProductWorkOrderReportList(req.Month)
+	if err != nil {
+		return err
+	}
+	rsp.Code = 200
+	rsp.Msg = "查询成功"
+	rsp.Data = resp
+
+	return nil
+}
+
+// Swagger:WorkOrderReport 产品线工单统计报表
+func (s *WorkOrderReportHandle) GetSupportWorkOrderReportList(ctx context.Context, req *sys_report.SearchPunchRecordsData, rsp *comm_def.CommonMsg) error {
+	svc, err := service.NewWorkOrderService(ctx)
+	if err != nil {
+		return err
+	}
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+
+	resp, err := svc.GetSupportWorkOrderReportList(req.Month)
+	if err != nil {
+		return err
+	}
+	rsp.Code = 200
+	rsp.Msg = "查询成功"
+	rsp.Data = resp
+	return nil
+}
+
+//  GetSaleWorkLoadReportList 查询工作量统计
+func (s *WorkOrderReportHandle) GetSupportWorkLoadReportList(ctx context.Context, req *sys_report.SearchWorkLoadData, rsp *comm_def.CommonMsg) error {
+	svc, err := service.NewWorkOrderService(ctx)
+	if err != nil {
+		return err
+	}
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+
+	resp, err := svc.GetSupportWorkLoadReportList(req)
+	if err != nil {
+		return err
+	}
+	rsp.Code = 200
+	rsp.Msg = "查询成功"
+	rsp.Data = resp
+	return nil
+}

+ 14 - 0
opms_parent/app/handler/work/deliver_order.go

@@ -108,3 +108,17 @@ func (w *DeliverOrder) Start(ctx context.Context, req *model.StartReq, rsp *comm
 	}
 	return nil
 }
+
+// GetHardwareUserInfo 获取硬件负责人信息
+func (w *DeliverOrder) GetHardwareUserInfo(ctx context.Context, req *model.HardwareReq, rsp *comm_def.CommonMsg) error {
+	s, err := workSrv.NewDeliverOrderService(ctx)
+	if err != nil {
+		return err
+	}
+	info, err := s.GetHardwareUserInfo(ctx, req)
+	if err != nil {
+		return err
+	}
+	rsp.Data = info
+	return nil
+}

+ 4 - 0
opms_parent/app/model/base/base_sales_region.go

@@ -38,3 +38,7 @@ type District struct {
 	RegionCode string `json:"regionCode" `
 	RegionDesc string `json:"regionDesc" `
 }
+
+type RegionTreeReq struct {
+	IsPermission string `json:"isPermission" `
+}

+ 4 - 4
opms_parent/app/model/contract/ctr_contract.go

@@ -43,10 +43,10 @@ type CtrContractListReq struct {
 	DistributorId   int    `json:"distributorId"`   // 经销商ID
 	DistributorName string `json:"distributorName"` // 经销商
 
-	ContractSignTimeStart string `p:"contractSignTimeStart"` //开始时间
-	ContractSignTimeEnd   string `p:"contractSignTimeEnd"`   //结束时间
-	CustProvinceId        int    `json:"custProvinceId"`     // 所在省ID
-	CustCityId            int    `json:"custCityId"`         // 所在市ID
+	ContractEndTimeStart string `p:"contractEndTimeStart"` //开始时间
+	ContractEndTimeEnd   string `p:"contractEndTimeEnd"`   //结束时间
+	CustProvinceId       int    `json:"custProvinceId"`    // 所在省ID
+	CustCityId           int    `json:"custCityId"`        // 所在市ID
 }
 
 type CtrAddProduct struct {

+ 5 - 0
opms_parent/app/model/contract/report.go

@@ -0,0 +1,5 @@
+package contract
+
+type QueryNumReq struct {
+	Date string `json:"date"`
+}

+ 5 - 0
opms_parent/app/model/proj/report.go

@@ -0,0 +1,5 @@
+package model
+
+type QueryNumReq struct {
+	Date string `json:"date"`
+}

+ 28 - 0
opms_parent/app/model/sys_report/sys_report.go

@@ -38,3 +38,31 @@ type IdsReq struct {
 type IdRequiredReq struct {
 	Id int `json:"id" v:"required#请输入Id"`
 }
+
+type SearchPunchRecordsData struct {
+	Month string `json:"month" v:"required#月份不能为空"`
+}
+
+type SearchWorkLoadData struct {
+	Month    string `json:"month"`
+	DateType string `json:"dateType"`
+}
+type WorkerOrderRtn struct {
+	SaleId          int    `orm:"sale_id"                  json:"saleId"`            // 销售工程师ID
+	SaleName        string `orm:"sale_name"                json:"saleName"`          // 销售工程师
+	ProductLine     string `orm:"product_line"                json:"productLine"`    // 产品线
+	ProductLineName string `json:"productLineName"`                                  // 产品线名称
+	AssignUserId    int    `orm:"assign_user_id"            json:"assignUserId"`     // 分派人员ID
+	AssignUserName  string `orm:"assign_user_name"            json:"assignUserName"` // 分派人员姓名
+	OrderTypeId     int    `orm:"order_type_id"            json:"orderTypeId"`       // 工单类型
+	OrderTypeName   string `orm:"order_type_name"          json:"orderTypeName"`     // 工单类型名称
+	OrderTypeNum    int    ` json:"orderTypeNum"`                                    // 工单类型数量
+}
+
+type WorkLoadRtn struct {
+	CreatedBy   int    `orm:"created_by"                  json:"createdBy"` // 销售工程师ID
+	CreatedName string `json:"createdName"`                                 // 销售工程师姓名
+	VisitCount  int    `json:"visitCount"`                                  // 拜访次数
+	OtherCount  int    `json:"otherCount"`                                  // 其他次数
+	TotalCount  int    `json:"totalCount"`                                  // 其他次数
+}

+ 19 - 4
opms_parent/app/model/work/deliver_order.go

@@ -5,6 +5,7 @@
 package work
 
 import (
+	contractmodel "dashoo.cn/micro/app/model/contract"
 	"dashoo.cn/micro/app/model/work/internal"
 	"dashoo.cn/opms_libary/request"
 	"github.com/gogf/gf/os/gtime"
@@ -16,9 +17,11 @@ type DeliverOrder internal.DeliverOrder
 // Fill with you ideas below.
 type DeliverOrderGetRsp struct {
 	DeliverOrder
-	SaleId  int                    `json:"saleId"`
-	Plan    []*DeliverOrderImpPlan `json:"plan"`
-	Product []*DeliverOrderProduct `json:"product"`
+	SaleId           int                       `json:"saleId"`
+	Plan             []*DeliverOrderImpPlan    `json:"plan"`
+	Product          []*DeliverOrderProduct    `json:"product"`
+	ProgressProducts []*DeliverProgressProduct `json:"progressProducts"`
+	Number           int                       `json:"number"` // 发货单数量
 }
 
 type DeliverOrderInfo struct {
@@ -46,7 +49,9 @@ type DeliverOrderListReq struct {
 }
 
 type DeliverOrderAddReq struct {
-	ContractId int `json:"contractId" v:"required#请输入合同ID"` // 关联合同ID
+	OrderTypeCode string                 `json:"orderTypeCode"`
+	ContractId    int                    `json:"contractId" v:"required#请输入合同ID"`           // 关联合同ID
+	FormData      []DingTalkFormItemData `json:"formData"         v:"required#表单数据不能为空"` // 表单数据
 }
 
 type DeliverOrderUpdateReq struct {
@@ -70,3 +75,13 @@ type StartReq struct {
 	ReceivingInfo        string      `json:"receivingInfo"`                      // 收货信息
 	SpecialRequirements  string      `json:"specialRequirements"`                // 特殊要求说明
 }
+
+type ProductInfo struct {
+	ProductLine string
+	Products    []*contractmodel.CtrContractProduct
+	Remark      string
+}
+
+type HardwareReq struct {
+	Name string `json:"name"`
+}

+ 8 - 7
opms_parent/app/model/work/deliver_order_imp_progress.go

@@ -23,6 +23,7 @@ type DeliverOrderProgressListReq struct {
 	ProgressType      string `json:"progressType"`      // 10发货任务单/20组装任务单/30部署安装单
 	ProgressLevel     string `json:"progressLevel"`     // 优先级(10最高 20普通 30较低 )
 	IsPrincipalPerson string `json:"isPrincipalPerson"` // 是否按照负责人查询
+	DeliverProgressId int    `json:"deliverProgressId"` // 关联发货任务单Id
 }
 
 type DeliverOrderProgressAddReq struct {
@@ -31,10 +32,10 @@ type DeliverOrderProgressAddReq struct {
 	ProgressContext string      `json:"progressContext" v:"required#请输入任务内容"` // 任务内容
 	StartDate       *gtime.Time `json:"startDate" v:"required#请输入开始时间"`       // 开始时间
 	EndDate         *gtime.Time `json:"endDate" v:"required#请输入结束时间"`         // 结束时间
-	ReaStartDate    *gtime.Time `json:"reaStartDate"`                                // 实际开始时间
-	ReaEndDate      *gtime.Time `json:"reaEndDate"`                                  // 实际结束时间
-	ProgressLevel   string      `json:"progressLevel"`                               // 优先级(10最高 20普通 30较低 )
-	Remark          string      `json:"remark"`                                      // 备注
+	ReaStartDate    *gtime.Time `json:"reaStartDate"`                         // 实际开始时间
+	ReaEndDate      *gtime.Time `json:"reaEndDate"`                           // 实际结束时间
+	ProgressLevel   string      `json:"progressLevel"`                        // 优先级(10最高 20普通 30较低 )
+	Remark          string      `json:"remark"`                               // 备注
 
 }
 
@@ -64,12 +65,12 @@ type DeliverOrderImpProgressFinishReq struct {
 }
 
 type StartDeliverGoodsProgressReq struct {
-	Progress *DeliverOrderImpProgress `json:"progress"`
-	Products []*productInfo           `json:"products"`
+	Progress *DeliverOrderImpProgress  `json:"progress"`
+	Products []*DeliverProgressProduct `json:"products"`
 }
 
 type productInfo struct {
-	DeliverOrderProduct
+	DeliverProgressProduct
 	OperateType string `json:"operateType"` // 外购;组装
 }
 

+ 14 - 0
opms_parent/app/model/work/deliver_progress_product.go

@@ -0,0 +1,14 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. Fill this file as you wish.
+// ==========================================================================
+
+package work
+
+import (
+	"dashoo.cn/micro/app/model/work/internal"
+)
+
+// DeliverProgressProduct is the golang structure for table deliver_progress_product.
+type DeliverProgressProduct internal.DeliverProgressProduct
+
+// Fill with you ideas below.

+ 1 - 0
opms_parent/app/model/work/internal/deliver_order_imp_progress.go

@@ -13,6 +13,7 @@ type DeliverOrderImpProgress struct {
 	Id                   int         `orm:"id,primary"              json:"id"`                   // 主键
 	DeliverOrderId       int         `orm:"deliver_order_id"        json:"deliverOrderId"`       // 关联交付订单ID
 	PlanId               int         `orm:"plan_id"                 json:"planId"`               // 关联实施计划
+	DeliverProgressId    int         `orm:"deliver_progress_id"     json:"deliverProgressId"`    // 关联发货任务单Id
 	ProgressTitle        string      `orm:"progress_title"          json:"progressTitle"`        // 任务标题
 	ProgressContext      string      `orm:"progress_context"        json:"progressContext"`      // 任务内容
 	StartDate            *gtime.Time `orm:"start_date"              json:"startDate"`            // 开始时间

+ 1 - 0
opms_parent/app/model/work/internal/deliver_order_product.go

@@ -16,6 +16,7 @@ type DeliverOrderProduct struct {
 	ProductName        string      `orm:"product_name"         json:"productName"`        // 产品名称
 	ProductType        string      `orm:"product_type"         json:"productType"`        // 产品类型
 	ProductNum         int         `orm:"product_num"          json:"productNum"`         // 产品数量
+	CompleteNum        int         `orm:"complete_num"         json:"completeNum"`        // 已完成数量
 	IsDeliver          string      `orm:"is_deliver"           json:"isDeliver"`          // 10 未开始;20 已操作
 	IsComplete         string      `orm:"is_complete"          json:"isComplete"`         // 10 未完成;20 组装或外购完成
 	IsInstall          string      `orm:"is_install"           json:"isInstall"`          // 10 未开始;20 安装部署完成

+ 35 - 0
opms_parent/app/model/work/internal/deliver_progress_product.go

@@ -0,0 +1,35 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"github.com/gogf/gf/os/gtime"
+)
+
+// DeliverProgressProduct is the golang structure for table deliver_progress_product.
+type DeliverProgressProduct struct {
+	Id                 int         `orm:"id,primary"           json:"id"`                 // 主键
+	DeliverOrderId     int         `orm:"deliver_order_id"     json:"deliverOrderId"`     // 关联交付订单ID
+	DeliverProgressId  int         `orm:"deliver_progress_id"  json:"deliverProgressId"`  // 关联的发货任务单Id
+	AssembleProgressId int         `orm:"assemble_progress_id" json:"assembleProgressId"` // 关联的组装任务单Id
+	InstallProgressId  int         `orm:"install_progress_id"  json:"installProgressId"`  // 关联的部署安装单
+	ProductId          int         `orm:"product_id"           json:"productId"`          // 关联产品Id
+	ProductCode        string      `orm:"product_code"         json:"productCode"`        // 产品编码
+	ProductName        string      `orm:"product_name"         json:"productName"`        // 产品名称
+	ProductType        string      `orm:"product_type"         json:"productType"`        // 产品类型
+	ProductNum         int         `orm:"product_num"          json:"productNum"`         // 产品数量
+	IsDeliver          string      `orm:"is_deliver"           json:"isDeliver"`          // 10 未开始;20 已操作
+	IsComplete         string      `orm:"is_complete"          json:"isComplete"`         // 10 未完成;20 组装或外购完成
+	IsInstall          string      `orm:"is_install"           json:"isInstall"`          // 10 未开始;20 安装部署完成
+	OperateType        string      `orm:"operate_type"         json:"operateType"`        // 获取方式:组装;外购
+	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"`        // 删除时间
+}

+ 2 - 1
opms_parent/app/model/work/work_order.go

@@ -32,7 +32,8 @@ type WorkOrderSearchReq struct {
 	SaleName         string      `json:"saleName"`         //销售工程师
 	UpdatedTimeStart *gtime.Time `json:"updatedTimeStart"` // 更新时间
 	UpdatedTimeEnd   *gtime.Time `json:"updatedTimeEnd"`   // 更新时间
-
+	SupportTime      string      `json:"supportTime"`      // 支持时间
+	ProductLine      string      `json:"productLine"`      // 产品线
 	request.PageReq
 }
 type WorkOrderReq struct {

+ 18 - 17
opms_parent/app/model/workflow/plat_workflow.go

@@ -11,23 +11,24 @@ import (
 
 // BizType 业务类型(10客户20项目创建30合同创建)
 const (
-	CustomerReceive  = "11" // 领取公海客户
-	CustomerPublic   = "12" // 客户移回公海
-	CustomerTrans    = "13" // 转移客户
-	ProjectCreate    = "20" // 项目创建
-	ProjectUpGrade   = "21" // 项目升级审批
-	ProjectDownGrade = "22" // 项目降级审批
-	ProjectTransfer  = "23" // 项目转移项目审批
-	ProjectToReserve = "24" // 项目转为储备项目审批
-	ProjectPersonnel = "25" // 项目协同人员审批
-	ContractCreate   = "30" // 合同创建
-	ContractInvoice  = "31" // 申请发票
-	PlatTaskApproval = "40" // 督办任务审批
-	DistProxyCreate  = "51" // 创建代理商
-	DistToProxy      = "52" // 经销商转代理商
-	DistProxyRenew   = "53" // 代理商续签
-	DistToDist       = "54" // 代理商转经销商
-	WorkOrderCreate  = "61" // 工单创建
+	CustomerReceive    = "11" // 领取公海客户
+	CustomerPublic     = "12" // 客户移回公海
+	CustomerTrans      = "13" // 转移客户
+	ProjectCreate      = "20" // 项目创建
+	ProjectUpGrade     = "21" // 项目升级审批
+	ProjectDownGrade   = "22" // 项目降级审批
+	ProjectTransfer    = "23" // 项目转移项目审批
+	ProjectToReserve   = "24" // 项目转为储备项目审批
+	ProjectPersonnel   = "25" // 项目协同人员审批
+	ContractCreate     = "30" // 合同创建
+	ContractInvoice    = "31" // 申请发票
+	PlatTaskApproval   = "40" // 督办任务审批
+	DistProxyCreate    = "51" // 创建代理商
+	DistToProxy        = "52" // 经销商转代理商
+	DistProxyRenew     = "53" // 代理商续签
+	DistToDist         = "54" // 代理商转经销商
+	WorkOrderCreate    = "61" // 支持工单创建
+	DeliverOrderCreate = "62" // 交付工单创建
 )
 
 // PlatWorkflow is the golang structure for table plat_workflow.

+ 40 - 0
opms_parent/app/service/base.go

@@ -194,6 +194,16 @@ func GetDictDataByType(ctx context.Context, typ string) (map[string]string, erro
 	return res, nil
 }
 
+// Find获取一个切片并在其中查找元素。如果找到它,它将返回它的密钥,否则它将返回-1和一个错误的bool。
+func FindItem(slice []string, val string) (int, bool) {
+	for i, item := range slice {
+		if item == val {
+			return i, true
+		}
+	}
+	return -1, false
+}
+
 // 有序
 func GetDictDataTreeByType(ctx context.Context, typ string) (*gmap.ListMap, error) {
 	data, err := baseGetDictDataByType(ctx, typ)
@@ -315,6 +325,36 @@ func GetUsersByRoleCode(ctx context.Context, roleCode []string, pageSize ...int)
 	return res, nil
 }
 
+// GetUserListByRoleCode 根据角色编码获取用户列表
+func GetUserListByRoleCode(ctx context.Context, roleCode []string, pageSize ...int) ([]map[string]interface{}, error) {
+	srv := micro_srv.InitMicroSrvClient("User", "micro_srv.auth")
+	defer srv.Close()
+	resp := &comm_def.CommonMsg{}
+	req := &SysUserSearchReq{Roles: roleCode, Status: "10"}
+	if len(pageSize) > 0 {
+		req.PageSize = pageSize[0]
+	}
+	err := srv.Call(ctx, "GetList", req, resp)
+	if err != nil {
+		return nil, myerrors.MicroCallError("根据角色编码获取用户失败")
+	}
+	if resp.Data == nil {
+		return nil, myerrors.TipsError("用户不存在")
+	}
+	data := resp.Data.(map[string]interface{})
+	list := data["list"].([]interface{})
+	var res []map[string]interface{}
+	for _, i := range list {
+		info := i.(map[string]interface{})
+		data := map[string]interface{}{
+			"Id":       gconv.Int(info["Id"]),
+			"NickName": info["NickName"].(string),
+		}
+		res = append(res, data)
+	}
+	return res, nil
+}
+
 // 获取用户权限
 func GetUserDataScope(userId int) (g.Map, error) {
 	srv := micro_srv.InitMicroSrvClient("User", "micro_srv.auth")

+ 2 - 2
opms_parent/app/service/base/base_product.go

@@ -41,10 +41,10 @@ func (s *productService) GetList(req *model.ProductSearchReq) (total int, produc
 		Dao = Dao.Where("prod_class = ?", req.ProdClass)
 	}
 	if req.OnlyHardware {
-		Dao = Dao.Where("prod_class in (40,60)", req.ProdClass)
+		Dao = Dao.Where("prod_class in (40,50,60)")
 	}
 	if req.OnlySoftware {
-		Dao = Dao.Where("prod_class in (10,20,30)", req.ProdClass)
+		Dao = Dao.Where("prod_class in (10,20,30)")
 	}
 
 	total, err = Dao.Count()

+ 37 - 7
opms_parent/app/service/base/base_sales_region.go

@@ -2,11 +2,11 @@ package base
 
 import (
 	"context"
-	"strconv"
-
+	"fmt"
 	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/os/gtime"
 	"github.com/gogf/gf/util/gconv"
+	"strconv"
 
 	"dashoo.cn/micro/app/dao/base"
 	model "dashoo.cn/micro/app/model/base"
@@ -59,18 +59,48 @@ func (s *salesRegionService) GetRegionList() (RegionList []*model.Region, err er
 }
 
 // GetRegionTree 获取大区及下属地区
-func (s *salesRegionService) GetRegionTree() (regionList []*model.Region, err error) {
-	err = s.Dao.Order("id asc").Scan(&regionList)
-	if err != nil {
-		return
+func (s *salesRegionService) GetRegionTree(req *model.RegionTreeReq) (regionList []*model.Region, err error) {
+	where1 := ""
+	where2 := ""
+	if req.IsPermission == "1" {
+		//	系统管理员、总经理、销售总监、销售助理看到所有区域
+		if service.StringsContains(s.CxtUser.Roles, "GeneralManager") || service.StringsContains(s.CxtUser.Roles, "SalesDirector") || service.StringsContains(s.CxtUser.Roles, "SaleAssociate") || service.StringsContains(s.CxtUser.Roles, "SysAdmin") {
+			//	无条件,查询全部
+		} else {
+			// 大区经理:看到大区及所负责的其他区域;销售工程师:看到所负责的区域
+			if data, ok := s.CxtUser.DataScope["cust_city_id"]; ok {
+				if data != nil {
+					idArr := data.([]interface{})
+					ids := "-1"
+					for _, id := range idArr {
+						ids += "," + gconv.String(id)
+					}
+					where2 = fmt.Sprintf("cust_city_id IN (%v)", ids)
+				}
+			}
+		}
 	}
+
 	detailDao := base.NewBaseSalesRegionDetailDao(s.Tenant)
 	regionDetailsList := ([]*model.District)(nil)
-	err = detailDao.Fields("region_id, cust_province_id as regionCode, cust_province as regionDesc").Group("cust_province_id").
+	err = detailDao.Where(where2).Fields("region_id, cust_province_id as regionCode, cust_province as regionDesc").Group("cust_province_id").
 		OrderAsc(detailDao.C.RegionId).Scan(&regionDetailsList)
 	if err != nil {
 		return
 	}
+	regionMap := make(map[int]int, 0)
+	regionIds := "-1"
+	for _, detail := range regionDetailsList {
+		if _, ok := regionMap[detail.RegionId]; !ok {
+			regionMap[detail.RegionId] = 1
+			regionIds += "," + gconv.String(detail.RegionId)
+		}
+	}
+	where1 += fmt.Sprintf("id IN (%v)", regionIds)
+	err = s.Dao.Order("created_time asc").Where(where1).Scan(&regionList)
+	if err != nil {
+		return
+	}
 	for _, item := range regionList {
 		item.Children = make([]*model.District, 0)
 		for _, v := range regionDetailsList {

+ 5 - 5
opms_parent/app/service/contract/ctr_contract.go

@@ -232,11 +232,11 @@ func (s CtrContractService) List(ctx context.Context, req *model.CtrContractList
 	if req.EndTime != "" {
 		dao = dao.Where("a.created_time < ?", req.EndTime)
 	}
-	if req.ContractSignTimeStart != "" {
-		dao = dao.Where("a.contract_sign_time >= ?", req.ContractSignTimeStart)
+	if req.ContractEndTimeStart != "" {
+		dao = dao.Where("a.contract_end_time >= ?", req.ContractEndTimeStart)
 	}
-	if req.ContractSignTimeEnd != "" {
-		dao = dao.Where("a.contract_sign_time <= ?", req.ContractSignTimeEnd)
+	if req.ContractEndTimeEnd != "" {
+		dao = dao.Where("a.contract_end_time <= ?", req.ContractEndTimeEnd)
 	}
 	if req.CustProvinceId != 0 {
 		dao = dao.Where("a.cust_province_id = ?", req.CustProvinceId)
@@ -799,7 +799,7 @@ func ContractApplyApproval(ctx context.Context, flow *workflowModel.PlatWorkflow
 	}
 
 	return contractDao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
-		_, err = worksrv.DeliverOrderAdd(tx, contractId, request.UserInfo{})
+		_, err = worksrv.DeliverOrderAdd(tx, contractId, request.UserInfo{}, nil)
 		return err
 	})
 }

+ 200 - 0
opms_parent/app/service/contract/report.go

@@ -0,0 +1,200 @@
+package service
+
+import (
+	"context"
+	dao "dashoo.cn/micro/app/dao/contract"
+	"dashoo.cn/micro/app/model/contract"
+	"dashoo.cn/micro/app/service"
+	"dashoo.cn/opms_libary/micro_srv"
+	"dashoo.cn/opms_libary/myerrors"
+	"fmt"
+	"github.com/gogf/gf/frame/g"
+)
+
+type ContractReportService struct {
+	Dao *dao.CtrContractDao
+	*service.ContextService
+}
+
+func NewContractReportService(ctx context.Context) (svc *ContractReportService, err error) {
+	tenant, err := micro_srv.GetTenant(ctx)
+	if err != nil {
+		err = myerrors.TipsError(fmt.Sprintf("获取租户码异常:%s", err.Error()))
+		return nil, err //fmt.Errorf("获取租户码异常:%s", err.Error())
+	}
+
+	svc = new(ContractReportService)
+	if svc.ContextService, err = svc.Init(ctx); err != nil {
+		return nil, err
+	}
+	svc.Dao = dao.NewCtrContractDao(tenant)
+	return svc, nil
+}
+
+type CollectionNumData struct {
+	contract.CtrContractCollection
+	InchargeId   int     `orm:"incharge_id"           json:"inchargeId"`   // 负责人ID
+	InchargeName string  `orm:"incharge_name"         json:"inchargeName"` // 负责人(销售工程师)
+	ProductLine  string  `orm:"product_line"          json:"productLine"`  // 产品线
+	Total        float64 `orm:"total"`                                     // 合计
+}
+
+// QueryCollectionNum 业绩指标-回款金额
+func (s *ContractReportService) QueryCollectionNum(date string) (interface{}, error) {
+	where := ""
+	// 权限限制(销售工程师看自己的)
+	if service.StringsContains(s.CxtUser.Roles, "SalesEngineer") {
+		where = fmt.Sprintf("b.incharge_id='%v'", s.CxtUser.Id)
+	}
+	// 获取数据
+	var collectionInfos []*CollectionNumData
+	err := s.Dao.DB.Model("ctr_contract_collection a").InnerJoin("ctr_contract b", "a.contract_id=b.id").Where(fmt.Sprintf("collection_datetime LIKE '%v%%'", date)).Where(where).Fields("a.*,b.incharge_id,b.incharge_name,b.product_line,SUM(a.collection_amount) total").Group("incharge_id, product_line").Order("incharge_id ASC, product_line ASC").Scan(&collectionInfos)
+	if err != nil {
+		return nil, err
+	}
+	// 获取销售数据
+	userList, err := service.GetUserListByRoleCode(s.Ctx, []string{"SalesEngineer"}, 1000)
+	if err != nil {
+		return nil, err
+	}
+	// 权限限制(销售工程师看自己的)
+	if service.StringsContains(s.CxtUser.Roles, "SalesEngineer") {
+		userList = []map[string]interface{}{
+			{
+				"Id":       s.CxtUser.Id,
+				"NickName": s.CxtUser.NickName,
+			},
+		}
+	}
+	// BIOBANK CELLSOP LIMS+基因 其他
+	header, data := make([]g.Map, 0), make([]g.Map, 0)
+	header = append(header, g.Map{"prop": "userName", "label": "销售工程师"}, g.Map{"prop": "bio", "label": "BIOBANK"}, g.Map{"prop": "cell", "label": "CELLSOP"}, g.Map{"prop": "lims", "label": "LIMS+基因"}, g.Map{"prop": "other", "label": "其他"}, g.Map{"prop": "total", "label": "合计"})
+
+	user2Collections := make(map[int][]*CollectionNumData, 0)
+	total := float64(0)
+	for _, col := range collectionInfos {
+		if _, ok := user2Collections[col.InchargeId]; !ok {
+			user2Collections[col.InchargeId] = make([]*CollectionNumData, 0)
+		}
+		user2Collections[col.InchargeId] = append(user2Collections[col.InchargeId], col)
+		total += col.Total
+	}
+	// 统计数据
+	for _, user := range userList {
+		bio, cell, lims, other, tot := float64(0), float64(0), float64(0), float64(0), float64(0)
+		if len(user2Collections[user["Id"].(int)]) > 0 {
+			for _, col := range user2Collections[user["Id"].(int)] {
+				tot += col.Total
+				if col.ProductLine == "10" {
+					bio += col.Total
+				} else if col.ProductLine == "20" {
+					cell += col.Total
+				} else if col.ProductLine == "30" {
+					lims += col.Total
+				} else {
+					other += col.Total
+				}
+			}
+		}
+		data = append(data, g.Map{
+			"userName": user["NickName"],
+			"bio":      fmt.Sprintf("%.2f", bio),
+			"cell":     fmt.Sprintf("%.2f", cell),
+			"lims":     fmt.Sprintf("%.2f", lims),
+			"other":    fmt.Sprintf("%.2f", other),
+			"total":    fmt.Sprintf("%.2f", tot),
+		})
+	}
+	data = append(data, g.Map{
+		"userName": "",
+		"bio":      "",
+		"cell":     "",
+		"lims":     "",
+		"other":    "",
+		"total":    fmt.Sprintf("总计:%.2f元", total),
+	})
+
+	return g.Map{"header": header, "data": data}, nil
+}
+
+// QueryContractNum 业绩指标-签约合同金额
+func (s *ContractReportService) QueryContractNum(date string) (interface{}, error) {
+	type ContractNumData struct {
+		contract.CtrContract
+		Total float64 `orm:"total"` // 合计
+	}
+	where := ""
+	// 权限限制(销售工程师看自己的)
+	if service.StringsContains(s.CxtUser.Roles, "SalesEngineer") {
+		where = fmt.Sprintf("incharge_id='%v'", s.CxtUser.Id)
+	}
+	// 获取数据
+	var contractInfos []*ContractNumData
+	err := s.Dao.Where(fmt.Sprintf("contract_sign_time LIKE '%v%%' AND appro_status='30'", date)).Where(where).Fields("ctr_contract.*,SUM(contract_amount) total").Group("incharge_id, product_line").Order("incharge_id ASC, product_line ASC").Scan(&contractInfos)
+	if err != nil {
+		return nil, err
+	}
+	// 获取销售数据
+	userList, err := service.GetUserListByRoleCode(s.Ctx, []string{"SalesEngineer"}, 1000)
+	if err != nil {
+		return nil, err
+	}
+	// 权限限制(销售工程师看自己的)
+	if service.StringsContains(s.CxtUser.Roles, "SalesEngineer") {
+		userList = []map[string]interface{}{
+			{
+				"Id":       s.CxtUser.Id,
+				"NickName": s.CxtUser.NickName,
+			},
+		}
+	}
+	// BIOBANK CELLSOP LIMS+基因 其他
+	header, data := make([]g.Map, 0), make([]g.Map, 0)
+	header = append(header, g.Map{"prop": "userName", "label": "销售工程师"}, g.Map{"prop": "bio", "label": "BIOBANK"}, g.Map{"prop": "cell", "label": "CELLSOP"}, g.Map{"prop": "lims", "label": "LIMS+基因"}, g.Map{"prop": "other", "label": "其他"}, g.Map{"prop": "total", "label": "合计"})
+
+	user2Contracts := make(map[int][]*ContractNumData, 0)
+	total := float64(0)
+	for _, col := range contractInfos {
+		if _, ok := user2Contracts[col.InchargeId]; !ok {
+			user2Contracts[col.InchargeId] = make([]*ContractNumData, 0)
+		}
+		user2Contracts[col.InchargeId] = append(user2Contracts[col.InchargeId], col)
+		total += col.Total
+	}
+	// 统计数据
+	for _, user := range userList {
+		bio, cell, lims, other, tot := float64(0), float64(0), float64(0), float64(0), float64(0)
+		if len(user2Contracts[user["Id"].(int)]) > 0 {
+			for _, col := range user2Contracts[user["Id"].(int)] {
+				tot += col.Total
+				if col.ProductLine == "10" {
+					bio += col.Total
+				} else if col.ProductLine == "20" {
+					cell += col.Total
+				} else if col.ProductLine == "30" {
+					lims += col.Total
+				} else {
+					other += col.Total
+				}
+			}
+		}
+		data = append(data, g.Map{
+			"userName": user["NickName"],
+			"bio":      fmt.Sprintf("%.2f", bio),
+			"cell":     fmt.Sprintf("%.2f", cell),
+			"lims":     fmt.Sprintf("%.2f", lims),
+			"other":    fmt.Sprintf("%.2f", other),
+			"total":    fmt.Sprintf("%.2f", tot),
+		})
+	}
+	data = append(data, g.Map{
+		"userName": "",
+		"bio":      "",
+		"cell":     "",
+		"lims":     "",
+		"other":    "",
+		"total":    fmt.Sprintf("总计:%.2f元", total),
+	})
+
+	return g.Map{"header": header, "data": data}, nil
+}

+ 2 - 2
opms_parent/app/service/home/report.go

@@ -758,7 +758,7 @@ func (s *HomeService) QuerySalesEngineerFollowUpNum(day *gtime.Time) (interface{
 		followUpMonthData = append(followUpMonthData, data)
 	}
 	// 409022238
-	userList, err := service.GetUsersByRoleCode(s.Ctx, []string{"SalesEngineer", "ProductLineManager"}, 100)
+	userList, err := service.GetUsersByRoleCode(s.Ctx, []string{"SalesEngineer"}, 100)
 	if err != nil {
 		return nil, err
 	}
@@ -810,7 +810,7 @@ func (s *HomeService) QueryPunchRecordsNum(day *gtime.Time) (interface{}, error)
 		punchRecordsMonthData = append(punchRecordsMonthData, data)
 	}
 	// 409022238
-	userList, err := service.GetUsersByRoleCode(s.Ctx, []string{"SalesEngineer", "ProductLineManager"}, 100)
+	userList, err := service.GetUsersByRoleCode(s.Ctx, []string{"SalesEngineer"}, 100)
 	if err != nil {
 		return nil, err
 	}

+ 3 - 3
opms_parent/app/service/plat/plat_task_cron.go

@@ -83,7 +83,7 @@ func (c taskCron) Run() {
 					// 校验当前时间
 					remindTime := gtime.NewFromStr(fmt.Sprintf("%v %v:%v:%v", now.Format("Y-m-d"), rules[2], rules[1], rules[0]))
 					// 10分钟一次定时循环,两者相差在10分钟之内(纳秒转换1e9)
-					if (now.Nanosecond()-remindTime.Nanosecond())/(1*60*1e9) <= 10 && now.Nanosecond() > remindTime.Nanosecond() {
+					if (now.UnixNano()-remindTime.UnixNano())/(1*60*1e9) <= 10 && now.UnixNano() > remindTime.UnixNano() {
 						taskNotifyMessage(task.MainUserId, task.OwnerUserId, TaskTitle+"督办需要处理,请前往执行")
 					}
 				} else if rules[3] == "?" { // 每周提醒
@@ -100,7 +100,7 @@ func (c taskCron) Run() {
 						// 校验当前时间
 						remindTime := gtime.NewFromStr(fmt.Sprintf("%v %v:%v:%v", now.Format("Y-m-d"), rules[2], rules[1], rules[0]))
 						// 10分钟一次定时循环,两者相差在10分钟之内(纳秒转换1e9)
-						if (now.Nanosecond()-remindTime.Nanosecond())/(1*60*1e9) <= 10 && now.Nanosecond() > remindTime.Nanosecond() {
+						if (now.UnixNano()-remindTime.UnixNano())/(1*60*1e9) <= 10 && now.UnixNano() > remindTime.UnixNano() {
 							taskNotifyMessage(task.MainUserId, task.OwnerUserId, TaskTitle+"督办需要处理,请前往执行")
 						}
 					}
@@ -117,7 +117,7 @@ func (c taskCron) Run() {
 						// 校验当前时间
 						remindTime := gtime.NewFromStr(fmt.Sprintf("%v %v:%v:%v", now.Format("Y-m-d"), rules[2], rules[1], rules[0]))
 						// 10分钟一次定时循环,两者相差在10分钟之内(纳秒转换1e9)
-						if (now.Nanosecond()-remindTime.Nanosecond())/(1*60*1e9) <= 10 && now.Nanosecond() > remindTime.Nanosecond() {
+						if (now.UnixNano()-remindTime.UnixNano())/(1*60*1e9) <= 10 && now.UnixNano() > remindTime.UnixNano() {
 							taskNotifyMessage(task.MainUserId, task.OwnerUserId, TaskTitle+"督办需要处理,请前往执行")
 						}
 					}

+ 114 - 0
opms_parent/app/service/proj/report.go

@@ -0,0 +1,114 @@
+package proj
+
+import (
+	"context"
+	dao "dashoo.cn/micro/app/dao/proj"
+	model "dashoo.cn/micro/app/model/proj"
+	"dashoo.cn/micro/app/service"
+	"dashoo.cn/opms_libary/micro_srv"
+	"dashoo.cn/opms_libary/myerrors"
+	"fmt"
+	"github.com/gogf/gf/frame/g"
+)
+
+type BusinessReportService struct {
+	Dao *dao.ProjBusinessDao
+	*service.ContextService
+}
+
+func NewBusinessReportService(ctx context.Context) (svc *BusinessReportService, err error) {
+	tenant, err := micro_srv.GetTenant(ctx)
+	if err != nil {
+		err = myerrors.TipsError(fmt.Sprintf("获取租户码异常:%s", err.Error()))
+		return nil, err //fmt.Errorf("获取租户码异常:%s", err.Error())
+	}
+
+	svc = new(BusinessReportService)
+	if svc.ContextService, err = svc.Init(ctx); err != nil {
+		return nil, err
+	}
+	svc.Dao = dao.NewProjBusinessDao(tenant)
+	return svc, nil
+}
+
+// QueryBusinessNum 业绩指标-当月新增项目
+func (s *BusinessReportService) QueryBusinessNum(date string) (interface{}, error) {
+	type BusinessNumData struct {
+		model.ProjBusiness
+		Total float64 `orm:"total"` // 合计
+	}
+	where := ""
+	// 权限限制(销售工程师看自己的)
+	if service.StringsContains(s.CxtUser.Roles, "SalesEngineer") {
+		where = fmt.Sprintf("sale_id='%v'", s.CxtUser.Id)
+	}
+	// 获取数据  (储备转C,项目来源为 400热线 10、展会信息获取 50)不记作新增数据
+	var businessInfos []*BusinessNumData
+	err := s.Dao.Where(fmt.Sprintf("created_time LIKE '%v%%' AND appro_status='30' AND nbo_source<>'10' AND nbo_source<>'50'", date)).Where(where).Fields("proj_business.*,COUNT(1) total").Group("sale_id, product_line").Order("sale_id ASC, product_line ASC").Scan(&businessInfos)
+	if err != nil {
+		return nil, err
+	}
+	// 获取销售数据
+	userList, err := service.GetUserListByRoleCode(s.Ctx, []string{"SalesEngineer"}, 1000)
+	if err != nil {
+		return nil, err
+	}
+	// 权限限制(销售工程师看自己的)
+	if service.StringsContains(s.CxtUser.Roles, "SalesEngineer") {
+		userList = []map[string]interface{}{
+			{
+				"Id":       s.CxtUser.Id,
+				"NickName": s.CxtUser.NickName,
+			},
+		}
+	}
+	// BIOBANK CELLSOP LIMS+基因 其他
+	header, data := make([]g.Map, 0), make([]g.Map, 0)
+	header = append(header, g.Map{"prop": "userName", "label": "销售工程师"}, g.Map{"prop": "bio", "label": "BIOBANK"}, g.Map{"prop": "cell", "label": "CELLSOP"}, g.Map{"prop": "lims", "label": "LIMS+基因"}, g.Map{"prop": "other", "label": "其他"}, g.Map{"prop": "total", "label": "合计"})
+
+	user2Business := make(map[int][]*BusinessNumData, 0)
+	total := float64(0)
+	for _, col := range businessInfos {
+		if _, ok := user2Business[col.SaleId]; !ok {
+			user2Business[col.SaleId] = make([]*BusinessNumData, 0)
+		}
+		user2Business[col.SaleId] = append(user2Business[col.SaleId], col)
+		total += col.Total
+	}
+	// 统计数据
+	for _, user := range userList {
+		bio, cell, lims, other, tot := float64(0), float64(0), float64(0), float64(0), float64(0)
+		if len(user2Business[user["Id"].(int)]) > 0 {
+			for _, col := range user2Business[user["Id"].(int)] {
+				tot += col.Total
+				if col.ProductLine == "10" {
+					bio += col.Total
+				} else if col.ProductLine == "20" {
+					cell += col.Total
+				} else if col.ProductLine == "30" {
+					lims += col.Total
+				} else {
+					other += col.Total
+				}
+			}
+		}
+		data = append(data, g.Map{
+			"userName": user["NickName"],
+			"bio":      fmt.Sprintf("%v", bio),
+			"cell":     fmt.Sprintf("%v", cell),
+			"lims":     fmt.Sprintf("%v", lims),
+			"other":    fmt.Sprintf("%v", other),
+			"total":    fmt.Sprintf("%v", tot),
+		})
+	}
+	data = append(data, g.Map{
+		"userName": "",
+		"bio":      "",
+		"cell":     "",
+		"lims":     "",
+		"other":    "",
+		"total":    fmt.Sprintf("总计:%v个", total),
+	})
+
+	return g.Map{"header": header, "data": data}, nil
+}

+ 155 - 0
opms_parent/app/service/sys_report/work_order.go

@@ -0,0 +1,155 @@
+package service
+
+import (
+	"context"
+	"dashoo.cn/micro/app/dao/plat"
+	"dashoo.cn/micro/app/dao/work"
+	"dashoo.cn/micro/app/model/sys_report"
+	"dashoo.cn/micro/app/service"
+	"database/sql"
+	"github.com/gogf/gf/errors/gerror"
+	"github.com/gogf/gf/os/glog"
+	"strings"
+)
+
+type WorkOrderService struct {
+	Dao     *work.WorkOrderDao
+	PlatDao *plat.PlatFollowupDao
+	*service.ContextService
+}
+
+func NewWorkOrderService(ctx context.Context) (svc *WorkOrderService, err error) {
+	svc = new(WorkOrderService)
+	if svc.ContextService, err = svc.Init(ctx); err != nil {
+		return nil, err
+	}
+	svc.Dao = work.NewWorkOrderDao(svc.Tenant)
+	svc.PlatDao = plat.NewPlatFollowupDao(svc.Tenant)
+	return svc, nil
+}
+
+// GetSaleWorkOrderReportList 查询销售工单统计
+func (s WorkOrderService) GetSaleWorkOrderReportList(month string) (list []*sys_report.WorkerOrderRtn, err error) {
+	db := s.Dao
+	if month != "" {
+		month = month[0:7]
+		err = db.Fields(s.Dao.C.SaleId, s.Dao.C.SaleName, s.Dao.C.OrderTypeId, s.Dao.C.OrderTypeName, "COUNT(order_type_id) AS OrderTypeNum").WhereLike(s.Dao.C.CreatedTime, "%"+month+"%").Group(s.Dao.C.SaleId, s.Dao.C.OrderTypeId).Scan(&list)
+
+	}
+	if month == "" {
+		err = db.Fields(s.Dao.C.SaleId, s.Dao.C.SaleName, s.Dao.C.OrderTypeId, s.Dao.C.OrderTypeName, "COUNT(order_type_id) AS OrderTypeNum").Group(s.Dao.C.SaleId, s.Dao.C.OrderTypeId).Scan(&list)
+	}
+
+	if err != nil && err != sql.ErrNoRows {
+		glog.Error("查询销售报表发生错误!")
+		return nil, gerror.New("查询销售报表发生错误!")
+	}
+
+	return list, nil
+}
+
+// GetSaleWorkOrderReportList 查询产品线工单统计
+func (s WorkOrderService) GetProductWorkOrderReportList(month string) (list []*sys_report.WorkerOrderRtn, err error) {
+	db := s.Dao
+	if month != "" {
+		month = month[0:7]
+		err = db.Fields(s.Dao.C.ProductLine, s.Dao.C.OrderTypeId, s.Dao.C.OrderTypeName, "COUNT(order_type_id) AS OrderTypeNum").WhereLike(s.Dao.C.CreatedTime, "%"+month+"%").Group(s.Dao.C.ProductLine, s.Dao.C.OrderTypeId).Scan(&list)
+
+	}
+
+	if month == "" {
+		err = db.Fields(s.Dao.C.ProductLine, s.Dao.C.OrderTypeId, s.Dao.C.OrderTypeName, "COUNT(order_type_id) AS OrderTypeNum").Group(s.Dao.C.ProductLine, s.Dao.C.OrderTypeId).Scan(&list)
+	}
+
+	if err != nil && err != sql.ErrNoRows {
+		glog.Error("查询销售报表发生错误!")
+		return nil, gerror.New("查询销售报表发生错误!")
+	}
+	//
+	res, err := service.GetDictDataByType(s.Ctx, "sys_product_line")
+	glog.Info("res的结果是:", res)
+	if err != nil {
+		glog.Error("字典查询调用失败")
+		return list, nil
+	}
+	var keyList []string
+	for k, _ := range res {
+		keyList = append(keyList, k)
+	}
+	for i := 0; i < len(list); i++ {
+		productLine := list[i].ProductLine
+		num, _ := service.FindItem(keyList, productLine)
+		if num != -1 {
+			list[i].ProductLineName = res[productLine]
+		}
+		if num == -1 {
+			list[i].ProductLineName = ""
+		}
+	}
+	return list, nil
+}
+
+// GetSaleWorkOrderReportList 查询支持人员工单统计
+func (s WorkOrderService) GetSupportWorkOrderReportList(month string) (list []*sys_report.WorkerOrderRtn, err error) {
+	db := s.Dao
+	if month != "" {
+		month = month[0:7]
+		err = db.Fields(s.Dao.C.AssignUserId, s.Dao.C.AssignUserName, s.Dao.C.OrderTypeId, s.Dao.C.OrderTypeName, "COUNT(order_type_id) AS OrderTypeNum").WhereLike(s.Dao.C.CreatedTime, "%"+month+"%").Group(s.Dao.C.AssignUserId, s.Dao.C.OrderTypeId).Scan(&list)
+
+	}
+	if month == "" {
+		err = db.Fields(s.Dao.C.AssignUserId, s.Dao.C.AssignUserName, s.Dao.C.OrderTypeId, s.Dao.C.OrderTypeName, "COUNT(order_type_id) AS OrderTypeNum").Group(s.Dao.C.AssignUserId, s.Dao.C.OrderTypeId).Scan(&list)
+	}
+
+	if err != nil && err != sql.ErrNoRows {
+		glog.Error("查询销售报表发生错误!")
+		return nil, gerror.New("查询销售报表发生错误!")
+	}
+
+	return list, nil
+}
+
+// GetSaleWorkOrderReportList 销售工作量统计
+func (s WorkOrderService) GetSupportWorkLoadReportList(req *sys_report.SearchWorkLoadData) (list []*sys_report.WorkLoadRtn, err error) {
+	date := req.Month
+	db := s.PlatDao
+
+	if req.DateType == "day" {
+		date = date[0:10]
+		db.Fields(s.PlatDao.C.CreatedBy, s.PlatDao.C.CreatedName, "SUM(CASE WHEN follow_type = 30 THEN 1 ELSE 0 END) AS VisitCount",
+			"SUM(CASE WHEN follow_type != 30 THEN 1 ELSE 0 END) AS OtherCount", " count(follow_type) as TotalCount").Where(s.PlatDao.C.FollowDate, date).Group(s.PlatDao.C.CreatedBy).Scan(&list)
+	} else if req.DateType == "week" {
+		dateArray := strings.Split(req.Month, ",")
+		dateStart := dateArray[0]
+		dateEnd := dateArray[1]
+		dateEnd = dateEnd[0:10] + " 23:59:59"
+		db.Fields(s.PlatDao.C.CreatedBy, s.PlatDao.C.CreatedName, "SUM(CASE WHEN follow_type = 30 THEN 1 ELSE 0 END) AS VisitCount",
+			"SUM(CASE WHEN follow_type != 30 THEN 1 ELSE 0 END) AS OtherCount", " count(follow_type) as TotalCount").WhereGTE(s.PlatDao.C.FollowDate, dateStart).WhereLTE(s.PlatDao.C.FollowDate, dateEnd).Group(s.PlatDao.C.CreatedBy).Scan(&list)
+	} else if req.DateType == "month" {
+		date = date[0:7]
+		db.Fields(s.PlatDao.C.CreatedBy, s.PlatDao.C.CreatedName, "SUM(CASE WHEN follow_type = 30 THEN 1 ELSE 0 END) AS VisitCount",
+			"SUM(CASE WHEN follow_type != 30 THEN 1 ELSE 0 END) AS OtherCount", " count(follow_type) as TotalCount").WhereLike(s.PlatDao.C.FollowDate, "%"+date+"%").Group(s.PlatDao.C.CreatedBy).Scan(&list)
+	}
+
+	if err != nil && err != sql.ErrNoRows {
+		glog.Error("查询跟进表数据发生错误!")
+		return list, gerror.New("数据处理发生错误!")
+	}
+	// 获取销售数据
+	userList, err := service.GetUserListByRoleCode(s.Ctx, []string{"SalesEngineer", "ProductLineManager"}, 1000)
+	if err != nil {
+		return nil, err
+	}
+	if len(list) > 0 {
+		for i := 0; i < len(list); i++ {
+			userId := list[i].CreatedBy
+			for j := 0; j < len(userList); j++ {
+				if userId == userList[j]["Id"] {
+					list[i].CreatedName = userList[j]["NickName"].(string)
+					break
+				}
+			}
+		}
+	}
+	return list, nil
+}

+ 253 - 36
opms_parent/app/service/work/deliver_order.go

@@ -2,10 +2,16 @@ package work
 
 import (
 	"context"
+	model "dashoo.cn/micro/app/model/base"
+	workflowModel "dashoo.cn/micro/app/model/workflow"
+	workflowService "dashoo.cn/micro/app/service/workflow"
+	"dashoo.cn/opms_libary/plugin/dingtalk/workflow"
 	"database/sql"
 	"fmt"
 	"github.com/gogf/gf/os/glog"
 	"github.com/gogf/gf/util/gconv"
+	"strconv"
+	"strings"
 
 	basedao "dashoo.cn/micro/app/dao/base"
 	contractdao "dashoo.cn/micro/app/dao/contract"
@@ -15,6 +21,7 @@ import (
 	contractmodel "dashoo.cn/micro/app/model/contract"
 	work "dashoo.cn/micro/app/model/work"
 	"dashoo.cn/micro/app/service"
+	"dashoo.cn/opms_libary/plugin/dingtalk/message"
 
 	"dashoo.cn/opms_libary/micro_srv"
 	"dashoo.cn/opms_libary/myerrors"
@@ -26,14 +33,15 @@ import (
 )
 
 type DeliverOrderService struct {
-	Dao             *workdao.DeliverOrderDao
-	PlanDao         *workdao.DeliverOrderImpPlanDao
-	ProductDao      *workdao.DeliverOrderProductDao
-	ContractDao     *contractdao.CtrContractDao
-	ProjBusinessDao *projdao.ProjBusinessDao
-	CustomerDao     *custdao.CustCustomerDao
-	CtrProductDao   *contractdao.CtrContractProductDao
-	BaseProductDao  *basedao.BaseProductDao
+	Dao                *workdao.DeliverOrderDao
+	PlanDao            *workdao.DeliverOrderImpPlanDao
+	ProductDao         *workdao.DeliverOrderProductDao
+	ContractDao        *contractdao.CtrContractDao
+	ProjBusinessDao    *projdao.ProjBusinessDao
+	CustomerDao        *custdao.CustCustomerDao
+	CtrProductDao      *contractdao.CtrContractProductDao
+	BaseProductDao     *basedao.BaseProductDao
+	ProgressProductDao *workdao.DeliverProgressProductDao
 
 	Tenant    string
 	userInfo  request.UserInfo
@@ -52,21 +60,23 @@ func NewDeliverOrderService(ctx context.Context) (*DeliverOrderService, error) {
 		return nil, fmt.Errorf("获取用户信息异常:%s", err.Error())
 	}
 	return &DeliverOrderService{
-		Dao:             workdao.NewDeliverOrderDao(tenant),
-		PlanDao:         workdao.NewDeliverOrderImpPlanDao(tenant),
-		ContractDao:     contractdao.NewCtrContractDao(tenant),
-		ProjBusinessDao: projdao.NewProjBusinessDao(tenant),
-		CustomerDao:     custdao.NewCustCustomerDao(tenant),
-		CtrProductDao:   contractdao.NewCtrContractProductDao(tenant),
-		ProductDao:      workdao.NewDeliverOrderProductDao(tenant),
-		BaseProductDao:  basedao.NewBaseProductDao(tenant),
-		Tenant:          tenant,
-		userInfo:        userInfo,
-		DataScope:       userInfo.DataScope,
+		Dao:                workdao.NewDeliverOrderDao(tenant),
+		PlanDao:            workdao.NewDeliverOrderImpPlanDao(tenant),
+		ContractDao:        contractdao.NewCtrContractDao(tenant),
+		ProjBusinessDao:    projdao.NewProjBusinessDao(tenant),
+		CustomerDao:        custdao.NewCustCustomerDao(tenant),
+		CtrProductDao:      contractdao.NewCtrContractProductDao(tenant),
+		ProductDao:         workdao.NewDeliverOrderProductDao(tenant),
+		BaseProductDao:     basedao.NewBaseProductDao(tenant),
+		ProgressProductDao: workdao.NewDeliverProgressProductDao(tenant),
+		Tenant:             tenant,
+		userInfo:           userInfo,
+		DataScope:          userInfo.DataScope,
 	}, nil
 }
 
 func (s DeliverOrderService) Get(ctx context.Context, id int) (*work.DeliverOrderGetRsp, error) {
+	number := 0
 	ent, err := s.Dao.Where("Id = ?", id).One()
 	if err != nil {
 		return nil, err
@@ -96,11 +106,23 @@ func (s DeliverOrderService) Get(ctx context.Context, id int) (*work.DeliverOrde
 	if proj != nil {
 		saleId = proj.SaleId
 	}
+	progressProducts, err := s.ProgressProductDao.Where("deliver_order_id = ?", id).All()
+	if err != nil {
+		return nil, err
+	}
+	// 发货单数量
+	number, err = s.Dao.DB.Model("deliver_order_imp_progress").Where(fmt.Sprintf("deliver_order_id='%v' AND progress_type='10'", id)).Count()
+	if err != nil {
+		return nil, err
+	}
+
 	return &work.DeliverOrderGetRsp{
-		DeliverOrder: *ent,
-		Plan:         plan,
-		Product:      product,
-		SaleId:       saleId,
+		DeliverOrder:     *ent,
+		Plan:             plan,
+		Product:          product,
+		ProgressProducts: progressProducts,
+		SaleId:           saleId,
+		Number:           number + 1,
 	}, nil
 }
 
@@ -222,16 +244,99 @@ func (s DeliverOrderService) Add(ctx context.Context, req *work.DeliverOrderAddR
 		return nil, myerrors.TipsError(validErr.Current().Error())
 	}
 
-	var id = []int{}
+	var productInfo work.ProductInfo
+
+	var products []*model.BaseProduct
+	err := s.Dao.DB.Model("base_product").Scan(&products)
+	if err != nil {
+		return nil, err
+	}
+
+	// 处理产品线
+	var pl string
+	for _, v := range req.FormData {
+		if v.Name == "产品线" {
+			pl, _ = v.Value.(string)
+		}
+		if v.Name == "备注" {
+			productInfo.Remark, _ = v.Value.(string)
+		}
+		if v.Name == "产品信息" {
+			pts := v.Value.([]interface{})
+			for _, fields := range pts {
+				var product contractmodel.CtrContractProduct
+				prodNum := 0
+				prodCode := ""
+				prodName := ""
+				for _, field := range fields.([]interface{}) {
+					data := field.(map[string]interface{})
+					if data["name"] == "产品名称" {
+						prodName = data["value"].(string)
+					}
+					if data["name"] == "产品型号" {
+						prodCode = data["value"].(string)
+					}
+					if data["name"] == "数量" {
+						prodNum = gconv.Int(data["value"])
+					}
+				}
+
+				product.ProdNum = prodNum
+				product.ProdCode = prodCode
+				product.ProdName = prodName
+				for _, p := range products {
+					if p.ProdCode == product.ProdCode && p.ProdName == product.ProdName {
+						product.ProdClass = p.ProdClass
+					}
+				}
+				productInfo.Products = append(productInfo.Products, &product)
+			}
+		}
+	}
+	if pl != "" {
+		productLine, err := service.GetDictDataByType(ctx, "sys_product_line")
+		if err != nil {
+			return nil, err
+		}
+		productLineMap := map[string]string{}
+		for k, v := range productLine {
+			productLineMap[v] = k
+		}
+		productInfo.ProductLine = productLineMap[pl]
+	}
+
+	var id []int
 	txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
 		var err error
-		id, err = DeliverOrderAdd(tx, req.ContractId, s.userInfo)
+		id, err = DeliverOrderAdd(tx, req.ContractId, s.userInfo, &productInfo)
+		if err != nil {
+			return err
+		}
+
+		// 提交工单 审批
+		workflowSrv, _ := workflowService.NewFlowService(ctx)
+		bizCode := gconv.String(id[0]) + ":" + req.OrderTypeCode
+		formComponentValues := make([]*workflow.StartProcessInstanceRequestFormComponentValues, 0)
+		if err = gconv.Structs(req.FormData, &formComponentValues); err != nil {
+			return err
+		}
+
+		workflowId, err := workflowSrv.StartProcessInstance(bizCode, workflowModel.DeliverOrderCreate, "", &workflow.StartProcessInstanceRequest{
+			ProcessCode:         &req.OrderTypeCode,
+			FormComponentValues: formComponentValues,
+		})
+		g.Log().Info("工单审批流ID ", workflowId)
+		if err != nil {
+			g.Log().Error(err)
+			return err
+		}
+
 		return err
 	})
 	return id, txerr
 }
 
-func DeliverOrderAdd(tx *gdb.TX, contractId int, userInfo request.UserInfo) ([]int, error) {
+func DeliverOrderAdd(tx *gdb.TX, contractId int, userInfo request.UserInfo, productInfo *work.ProductInfo) ([]int, error) {
 	var c contractmodel.CtrContract
 	err := tx.GetStruct(&c, "select * from ctr_contract where id = ?", contractId)
 	if err == sql.ErrNoRows {
@@ -242,12 +347,18 @@ func DeliverOrderAdd(tx *gdb.TX, contractId int, userInfo request.UserInfo) ([]i
 	}
 
 	var product []*contractmodel.CtrContractProduct
-	err = tx.GetStructs(&product, "select * from ctr_contract_product where contract_id = ?", contractId)
-	if err == sql.ErrNoRows {
-		return nil, myerrors.TipsError(fmt.Sprintf("合同产品为空: %d", contractId))
-	}
-	if err != nil {
-		return nil, err
+	remark := ""
+	if productInfo == nil {
+		err = tx.GetStructs(&product, "select * from ctr_contract_product where contract_id = ?", contractId)
+		if err == sql.ErrNoRows {
+			return nil, myerrors.TipsError(fmt.Sprintf("合同产品为空: %d", contractId))
+		}
+		if err != nil {
+			return nil, err
+		}
+	} else {
+		product = append(product, productInfo.Products...)
+		remark = productInfo.Remark
 	}
 
 	var deliverSoft *work.DeliverOrder
@@ -263,7 +374,8 @@ func DeliverOrderAdd(tx *gdb.TX, contractId int, userInfo request.UserInfo) ([]i
 		if p.ProdClass == "10" || p.ProdClass == "20" || p.ProdClass == "30" {
 			orderType = "10"
 		}
-		if p.ProdClass == "40" || p.ProdClass == "60" {
+		// 参考218上的产品类型设置
+		if p.ProdClass == "40" || p.ProdClass == "50" || p.ProdClass == "60" {
 			orderType = "20"
 		}
 
@@ -272,10 +384,15 @@ func DeliverOrderAdd(tx *gdb.TX, contractId int, userInfo request.UserInfo) ([]i
 		if orderType == "20" {
 			projectManId, projectManName, deliverManId, deliverManName = projectManId1, projectManName1, deliverManId1, deliverManName1
 		}
+		line := c.ProductLine
+		if productInfo != nil {
+			line = productInfo.ProductLine
+		}
 
+		// 交付状态(0发起 10项目立项 15进行中 20 完成 30审批拒绝40关闭)
 		o := work.DeliverOrder{
 			OrderCode:      fmt.Sprintf("%s%s", c.ContractCode, orderType),
-			OrderStatus:    "10",
+			OrderStatus:    "0",
 			OrderType:      orderType,
 			CustId:         c.CustId,
 			CustName:       c.CustName,
@@ -287,8 +404,8 @@ func DeliverOrderAdd(tx *gdb.TX, contractId int, userInfo request.UserInfo) ([]i
 			ProjectManName: projectManName,
 			DeliverManId:   deliverManId,
 			DeliverManName: deliverManName,
-			Product:        c.ProductLine,
-			Remark:         "",
+			Product:        line,
+			Remark:         remark,
 			CreatedBy:      int(userInfo.Id),
 			CreatedName:    userInfo.NickName,
 			CreatedTime:    gtime.Now(),
@@ -349,6 +466,91 @@ func DeliverOrderAdd(tx *gdb.TX, contractId int, userInfo request.UserInfo) ([]i
 	return id, nil
 }
 
+// DeliverOrderNotify 工单 审批结果通知
+func (s *DeliverOrderService) DeliverOrderNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
+	bizCode := strings.Split(flow.BizCode, ":")
+	if len(bizCode) != 2 {
+		return fmt.Errorf("工单审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
+	}
+	workOrderId := bizCode[0]
+	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)
+	}
+	fmt.Println(msg)
+
+	workOrder, err := s.Dao.WherePri(workOrderId).One()
+	if err != nil {
+		return err
+	}
+	if workOrder == nil {
+		return fmt.Errorf("工单不存在:%s Id: %d", flow.BizCode, flow.Id)
+	}
+
+	var data = g.Map{}
+	// 工单状态(10发起20审批中30审批通过40审批拒绝50关闭)
+	// 交付状态(0发起 10项目立项 15进行中 20 完成 30审批拒绝40关闭)
+	if msg.ProcessType == "terminate" {
+		data[s.Dao.C.OrderStatus] = "40"
+	}
+	if msg.ProcessType == "finish" && msg.Result == "refuse" {
+		data[s.Dao.C.OrderStatus] = "30"
+	}
+	if msg.ProcessType == "finish" && msg.Result == "agree" {
+		data[s.Dao.C.OrderStatus] = "10"
+	}
+
+	if data[s.Dao.C.OrderStatus] == "10" {
+		s.workOrderSendMsg(workOrder, "交付工单审批通过提醒", fmt.Sprintf("<p>工单:%s 已审批通过</p>", workOrder.OrderCode))
+	}
+
+	// 项目修改
+	_, err = s.Dao.WherePri(workOrder.Id).Update(fmt.Sprintf("order_status='%v'", data[s.Dao.C.OrderStatus]))
+	if err != nil {
+		return err
+	}
+	return err
+}
+
+func (s *DeliverOrderService) workOrderSendMsg(order *work.DeliverOrder, title, content string) {
+	recvUserIds := []int{}
+	if order.ProjectManId != 0 {
+		recvUserIds = append(recvUserIds, order.ProjectManId)
+	}
+	if order.DeliverManId != 0 {
+		recvUserIds = append(recvUserIds, order.DeliverManId)
+	}
+	contract, err := s.ContractDao.Where(fmt.Sprintf("id='%v'", order.ContractId)).One()
+	if err != nil {
+		glog.Error(err)
+	}
+	if contract != nil {
+		recvUserIds = append(recvUserIds, contract.InchargeId)
+	}
+	recvUserIds = service.SliceIntDeduplication(recvUserIds)
+	if len(recvUserIds) == 0 {
+		return
+	}
+	recvUserIdString := []string{}
+	for _, uid := range recvUserIds {
+		recvUserIdString = append(recvUserIdString, strconv.Itoa(uid))
+	}
+	msg := g.MapStrStr{
+		"msgTitle":    title,
+		"msgContent":  content,
+		"msgType":     "20",
+		"recvUserIds": strings.Join(recvUserIdString, ","),
+		"msgStatus":   "10",
+		"sendType":    "10",
+	}
+	fmt.Println(title, strings.Join(recvUserIdString, ","))
+	if err := service.CreateSystemMessage(msg); err != nil {
+		g.Log().Error("交付工单 %s 提醒异常:%s", title, err)
+	}
+}
+
 func getProjectUser(tx *gdb.TX, c *contractmodel.CtrContract, isDeliver bool) (int, string, int, string) {
 	projectManId, projectManName, deliverManId, deliverManName := 0, "", 0, ""
 	// 根据产品线,设置项目经理:  10 BIOBANK; 20 CELLSOP; 30 LIMS+基因; 40 智能硬件; 50 液氮罐; 60 MCS;
@@ -538,3 +740,18 @@ func (s DeliverOrderService) Start(ctx context.Context, req *work.StartReq) erro
 
 	return err
 }
+
+func (s DeliverOrderService) GetHardwareUserInfo(ctx context.Context, req *work.HardwareReq) (map[string]interface{}, error) {
+	user, err := s.Dao.DB.Model("sys_user").Where(fmt.Sprintf("nick_name='%v'", req.Name)).One()
+	if err != nil {
+		if err == sql.ErrNoRows {
+			return nil, nil
+		}
+		return nil, err
+	}
+
+	return map[string]interface{}{
+		"id":       user["id"],
+		"nickName": user["nick_name"],
+	}, nil
+}

+ 2 - 2
opms_parent/app/service/work/deliver_order_cron.go

@@ -15,7 +15,7 @@ import (
 func init() {
 	// 定时任务
 	c := cron.New()
-	spec := "1 0/10 * * * ?" // 每天10分钟执行一次
+	spec := "1 0/1 * * * ?" // 每天10分钟执行一次
 
 	if err := c.AddJob(spec, deliverOrderProgressCron{}); err != nil {
 		glog.Error(err)
@@ -46,7 +46,7 @@ func (c deliverOrderProgressCron) Run() {
 		// 校验当前时间
 		remindTime := p["estimated_arrival_time"].GTime()
 		// 10分钟一次定时循环,两者相差在10分钟之内(纳秒转换1e9)
-		if (now.Nanosecond()-remindTime.Nanosecond())/(1*60*1e9) <= 10 {
+		if (now.UnixNano()-remindTime.UnixNano())/(1*60*1e9) <= 10 {
 			ids := gconv.String(p["principal_person_id"])
 			if gconv.String(p["sale_id"]) != gconv.String(p["principal_person_id"]) {
 				ids += "," + gconv.String(p["sale_id"])

+ 139 - 57
opms_parent/app/service/work/deliver_order_progress.go

@@ -20,11 +20,12 @@ import (
 )
 
 type DeliverOrderProgressService struct {
-	Dao         *workdao.DeliverOrderImpProgressDao
-	PlanDao     *workdao.DeliverOrderImpPlanDao
-	OrderDao    *workdao.DeliverOrderDao
-	ProductDao  *workdao.DeliverOrderProductDao
-	ContractDao *contractdao.CtrContractDao
+	Dao                *workdao.DeliverOrderImpProgressDao
+	PlanDao            *workdao.DeliverOrderImpPlanDao
+	OrderDao           *workdao.DeliverOrderDao
+	ProductDao         *workdao.DeliverOrderProductDao
+	ProgressProductDao *workdao.DeliverProgressProductDao
+	ContractDao        *contractdao.CtrContractDao
 
 	Tenant    string
 	userInfo  request.UserInfo
@@ -43,14 +44,15 @@ func NewDeliverOrderProgressService(ctx context.Context) (*DeliverOrderProgressS
 		return nil, fmt.Errorf("获取用户信息异常:%s", err.Error())
 	}
 	return &DeliverOrderProgressService{
-		Dao:         workdao.NewDeliverOrderImpProgressDao(tenant),
-		PlanDao:     workdao.NewDeliverOrderImpPlanDao(tenant),
-		OrderDao:    workdao.NewDeliverOrderDao(tenant),
-		ContractDao: contractdao.NewCtrContractDao(tenant),
-		ProductDao:  workdao.NewDeliverOrderProductDao(tenant),
-		Tenant:      tenant,
-		userInfo:    userInfo,
-		DataScope:   userInfo.DataScope,
+		Dao:                workdao.NewDeliverOrderImpProgressDao(tenant),
+		PlanDao:            workdao.NewDeliverOrderImpPlanDao(tenant),
+		OrderDao:           workdao.NewDeliverOrderDao(tenant),
+		ContractDao:        contractdao.NewCtrContractDao(tenant),
+		ProductDao:         workdao.NewDeliverOrderProductDao(tenant),
+		ProgressProductDao: workdao.NewDeliverProgressProductDao(tenant),
+		Tenant:             tenant,
+		userInfo:           userInfo,
+		DataScope:          userInfo.DataScope,
 	}, nil
 }
 
@@ -59,6 +61,9 @@ func (s DeliverOrderProgressService) List(ctx context.Context, req *work.Deliver
 	if req.DeliverOrderId != 0 {
 		dao = dao.Where("deliver_order_id = ?", req.DeliverOrderId)
 	}
+	if req.DeliverProgressId != 0 {
+		dao = dao.Where("deliver_progress_id = ?", req.DeliverProgressId)
+	}
 	if req.PlanId != 0 {
 		dao = dao.Where("plan_id = ?", req.PlanId)
 	}
@@ -301,9 +306,10 @@ func (s DeliverOrderProgressService) StartDeliverGoodsProgress(ctx context.Conte
 			return err
 		}
 		// 初始化数据
-		deliverProgress.ProgressStatus = "10" // 状态(10未开始20进行中30已完成)
-		deliverProgress.DeliverStatus = "10"  // 发货状态(10未开始、20进行中、30已发货、40产品已验收、50确认已到货、60安装完成)
+		deliverProgress.ProgressStatus = "20" // 状态(10未开始20进行中30已完成)
+		deliverProgress.DeliverStatus = "20"  // 发货状态(10未开始、20进行中、30已发货、40产品已验收、50确认已到货、60安装完成)
 		//deliverProgress.ProgressType = "10"   // 10发货任务单/20组装任务单/30部署安装单
+		deliverProgress.ReaStartDate = gtime.Now()
 		if deliverProgress.PrincipalPerson == "" {
 			deliverProgress.PrincipalPersonId, deliverProgress.PrincipalPerson, err = s.getUserInfo("丁岳嵩")
 		}
@@ -327,21 +333,21 @@ func (s DeliverOrderProgressService) StartDeliverGoodsProgress(ctx context.Conte
 		}
 		service.SetCreatedInfo(&assembleProgress, s.userInfo.Id, s.userInfo.NickName)
 
-		progressIds := ""
-		assembleIds := ""
-		for _, product := range req.Products {
-			if progressIds == "" {
-				progressIds = gconv.String(product.Id)
-			} else {
-				progressIds += "," + gconv.String(product.Id)
-			}
+		var indexArr []int
+		for index, product := range req.Products {
+			product.Id = 0
+			product.UpdatedName = ""
+			product.UpdatedTime = nil
+			product.UpdatedBy = 0
+			service.SetCreatedInfo(product, s.userInfo.Id, s.userInfo.NickName)
+
 			// 外购;组装
 			if product.OperateType == "组装" {
-				if assembleIds == "" {
-					assembleIds = gconv.String(product.Id)
-				} else {
-					assembleIds += "," + gconv.String(product.Id)
-				}
+				indexArr = append(indexArr, index)
+			}
+			_, err = tx.Update("deliver_order_product", fmt.Sprintf("complete_num=IFNULL(complete_num,0) + %v", product.ProductNum), fmt.Sprintf("id='%v'", product.ProductId))
+			if err != nil {
+				return err
 			}
 		}
 
@@ -352,25 +358,30 @@ func (s DeliverOrderProgressService) StartDeliverGoodsProgress(ctx context.Conte
 		}
 
 		deliverId, _ := result1.LastInsertId()
-		if progressIds != "" {
-			_, err = tx.Update("deliver_order_product", fmt.Sprintf("is_deliver='20',deliver_progress_id='%v',operate_type='外购'", deliverId), fmt.Sprintf("id IN (%v)", progressIds))
-			if err != nil {
-				return err
-			}
+		for _, product := range req.Products {
+			product.IsDeliver = "20"
+			product.DeliverProgressId = int(deliverId)
+			product.OperateType = "外购"
 		}
+		assembleProgress.DeliverProgressId = int(deliverId)
 		// 存在硬件安装
-		if assembleIds != "" {
+		if len(indexArr) > 0 {
 			result2, err := tx.Save("deliver_order_imp_progress", assembleProgress)
 			if err != nil {
 				return err
 			}
 			assembleId, _ := result2.LastInsertId()
-			_, err = tx.Update("deliver_order_product", fmt.Sprintf("assemble_progress_id='%v',operate_type='组装'", assembleId), fmt.Sprintf("id IN (%v)", assembleIds))
-			if err != nil {
-				return err
+			for _, ind := range indexArr {
+				req.Products[ind].AssembleProgressId = int(assembleId)
+				req.Products[ind].OperateType = "组装"
 			}
 		}
 
+		_, err = tx.Save("deliver_progress_product", req.Products)
+		if err != nil {
+			return err
+		}
+
 		return nil
 	})
 	if err != nil {
@@ -394,7 +405,7 @@ func (s DeliverOrderProgressService) CompleteAssembleGoodsProgress(ctx context.C
 	if err != nil {
 		return err
 	}
-	_, err = s.ProductDao.Update("is_complete='20'", fmt.Sprintf("assemble_progress_id='%v'", req.Id))
+	_, err = s.ProgressProductDao.Update("is_complete='20'", fmt.Sprintf("assemble_progress_id='%v'", req.Id))
 
 	return err
 }
@@ -405,23 +416,77 @@ func (s DeliverOrderProgressService) DeliverGoods(ctx context.Context, req *work
 	if err != nil {
 		return err
 	}
+	// 10发货任务单/20组装任务单/30部署安装单
+	installProgress, err := s.Dao.Where(fmt.Sprintf("deliver_order_id='%v' AND progress_status<>'30' AND progress_type='30'", progress.DeliverOrderId)).FindOne()
+	if err != nil && err != sql.ErrNoRows {
+		return err
+	}
+
+	err = s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+		_, err = tx.Update("deliver_order_imp_progress", fmt.Sprintf("deliver_status='30',express_name='%v',express_code='%v',estimated_arrival_time='%v'", req.ExpressName, req.ExpressCode, req.EstimatedArrivalTime), fmt.Sprintf("id='%v'", req.Id))
+		if err != nil {
+			return err
+		}
+
+		if installProgress != nil {
+			_, err = tx.Update("deliver_progress_product", fmt.Sprintf("install_progress_id='%v'", installProgress.Id), fmt.Sprintf("deliver_progress_id='%v'", req.Id))
+			if err != nil {
+				return err
+			}
+		} else {
+			// 生成部署安装计划
+			var plan work.DeliverOrderImpPlan
+			plan.DeliverOrderId = progress.DeliverOrderId
+			plan.PlanTitle = "部署安装计划"
+			plan.PlanStatus = "10"
+			plan.PlanStartDate = gtime.Now()
+			plan.PlanEndDate = req.EstimatedArrivalTime
+			service.SetCreatedInfo(&plan, s.userInfo.Id, s.userInfo.NickName)
+			r, err := tx.Save("deliver_order_imp_plan", plan)
+			if err != nil {
+				return err
+			}
+			planId, _ := r.LastInsertId()
+
+			// 生成部署安装任务(只存在一个未完成的部署安装任务)
+			var insProgress work.DeliverOrderImpProgress
+			insProgress.PlanId = int(planId)
+			insProgress.DeliverOrderId = progress.DeliverOrderId
+			insProgress.DeliverProgressId = req.Id
+			insProgress.ProgressTitle = "安装任务单"
+			insProgress.StartDate = gtime.Now()
+			insProgress.EndDate = progress.EndDate
+			insProgress.ProgressStatus = "10" // 状态(10未开始20进行中30已完成
+			insProgress.ProgressLevel = "10"  // 优先级
+			insProgress.ProgressType = "30"   // 10发货任务单/20组装任务单/30部署安装单
+			if insProgress.PrincipalPerson == "" {
+				insProgress.PrincipalPersonId, insProgress.PrincipalPerson, err = s.getUserInfo("王志强")
+				if err != nil {
+					return err
+				}
+			}
+			service.SetCreatedInfo(&insProgress, s.userInfo.Id, s.userInfo.NickName)
 
-	_, err = s.Dao.Update(fmt.Sprintf("deliver_status='30',express_name='%v',express_code='%v',estimated_arrival_time='%v'", req.ExpressName, req.ExpressCode, req.EstimatedArrivalTime), fmt.Sprintf("id='%v'", req.Id))
+			// 保存数据
+			result1, err := tx.Save("deliver_order_imp_progress", insProgress)
+			if err != nil {
+				return err
+			}
 
-	// 生成部署安装计划
-	var plan work.DeliverOrderImpPlan
-	plan.DeliverOrderId = progress.DeliverOrderId
-	plan.PlanTitle = "部署安装计划"
-	plan.PlanStatus = "10"
-	plan.PlanStartDate = gtime.Now()
-	plan.PlanEndDate = req.EstimatedArrivalTime
-	service.SetCreatedInfo(&plan, s.userInfo.Id, s.userInfo.NickName)
-	_, err = s.PlanDao.Save(plan)
+			id, _ := result1.LastInsertId()
+			_, err = tx.Update("deliver_progress_product", fmt.Sprintf("install_progress_id='%v'", id), fmt.Sprintf("deliver_progress_id='%v'", req.Id))
+			if err != nil {
+				return err
+			}
+
+		}
+
+		return nil
+	})
 	if err != nil {
 		return err
 	}
-
-	return err
+	return nil
 }
 
 // InspectGoods 验收
@@ -453,9 +518,9 @@ func (s DeliverOrderProgressService) StartInstallProgress(ctx context.Context, r
 		progress.ProgressType = "30"   // 10发货任务单/20组装任务单/30部署安装单
 		if progress.PrincipalPerson == "" {
 			progress.PrincipalPersonId, progress.PrincipalPerson, err = s.getUserInfo("王志强")
-		}
-		if err != nil {
-			return err
+			if err != nil {
+				return err
+			}
 		}
 		service.SetCreatedInfo(&progress, s.userInfo.Id, s.userInfo.NickName)
 
@@ -475,7 +540,7 @@ func (s DeliverOrderProgressService) StartInstallProgress(ctx context.Context, r
 			}
 		}
 
-		_, err = tx.Update("deliver_order_product", fmt.Sprintf("install_progress_id='%v'", deliverId), fmt.Sprintf("id IN (%v)", ids))
+		_, err = tx.Update("deliver_progress_product", fmt.Sprintf("install_progress_id='%v'", deliverId), fmt.Sprintf("id IN (%v)", ids))
 		if err != nil {
 			return err
 		}
@@ -494,7 +559,11 @@ func (s DeliverOrderProgressService) CompleteInstall(ctx context.Context, req *w
 	if err != nil {
 		return err
 	}
-	allProducts, err := s.ProductDao.Where(fmt.Sprintf("deliver_order_id='%v'", progress.DeliverOrderId)).FindAll()
+	count, err := s.ProductDao.Where(fmt.Sprintf("deliver_order_id='%v' AND product_num<>complete_num", progress.DeliverOrderId)).Count()
+	if err != nil {
+		return err
+	}
+	allProducts, err := s.ProgressProductDao.Where(fmt.Sprintf("deliver_order_id='%v'", progress.DeliverOrderId)).FindAll()
 	if err != nil {
 		return err
 	}
@@ -536,17 +605,30 @@ func (s DeliverOrderProgressService) CompleteInstall(ctx context.Context, req *w
 		}
 		// 更新发货任务单状态
 		if progressIds != "" {
-			_, err = tx.Update("deliver_order_imp_progress", "deliver_status='60'", fmt.Sprintf("id IN (%v)", progressIds))
+			_, err = tx.Update("deliver_order_imp_progress", fmt.Sprintf("deliver_status='60',progress_status='30',rea_end_date='%v'", gtime.Now().Format("Y-m-d H:i:s")), fmt.Sprintf("id IN (%v)", progressIds))
 			if err != nil {
 				return err
 			}
 		}
 		// 更新产品状态
 		if ids != "" {
-			_, err = tx.Update("deliver_order_product", "is_install='20'", fmt.Sprintf("id IN (%v)", ids))
+			_, err = tx.Update("deliver_progress_product", "is_install='20'", fmt.Sprintf("id IN (%v)", ids))
+			if err != nil {
+				return err
+			}
+		}
+		// 更新硬件交付工单完成状态
+		if count == 0 {
+			count1, err := tx.Model("deliver_order_imp_progress").Where(fmt.Sprintf("(progress_status='20' OR progress_status='10') AND progress_type='10' AND deliver_progress_id='%v'", progress.DeliverOrderId)).Count()
 			if err != nil {
 				return err
 			}
+			if count1 == 0 {
+				_, err = tx.Update("deliver_order", fmt.Sprintf("order_status='20',finish_time='%v'", gtime.Now().Format("Y-m-d H:i:s")), fmt.Sprintf("id='%v'", progress.DeliverOrderId))
+				if err != nil {
+					return err
+				}
+			}
 		}
 
 		return nil

+ 6 - 0
opms_parent/app/service/work/work_order.go

@@ -125,6 +125,12 @@ func (s *OrderService) GetList(req *model.WorkOrderSearchReq) (total int, orderL
 	if req.SaleName != "" {
 		db = db.WhereLike("a."+s.Dao.C.SaleName, "%"+req.SaleName+"%")
 	}
+	if req.SupportTime != "" {
+		db = db.Where("a."+s.Dao.C.SupportTime, req.SupportTime)
+	}
+	if req.ProductLine != "" {
+		db = db.Where("b.product_line", req.ProductLine)
+	}
 	total, err = db.Count()
 	if err != nil {
 		err = myerrors.DbError("获取总行数失败。")

+ 3 - 0
opms_parent/main.go

@@ -68,10 +68,13 @@ func main() {
 	s.RegisterName("DingUpload", new(dingtalk.DingUploadHandler), "")
 	s.RegisterName("Report", new(sysreport.SysReportHandler), "")
 	s.RegisterName("RoleReport", new(sysreport.SysRoleReportHandler), "")
+	s.RegisterName("WorkOrderReport", new(sysreport.WorkOrderReportHandle), "")
 	s.RegisterName("CustCustomerBidRecord", new(cust.CustCustomerBidRecordHandler), "")
 	s.RegisterName("CustCustomerInvoiceHeader", new(cust.CustCustomerInvoiceHeaderHandler), "")
 	s.RegisterName("Questionnaire", new(plat.QuestionnaireHandler), "")
 	s.RegisterName("TableColsConfig", new(plat.TableColsConfigHandler), "")
+	s.RegisterName("ContractReport", new(contract.ContractReportHandler), "")
+	s.RegisterName("BusinessReport", new(projHandler.BusinessReportHandler), "")
 
 	// 首页
 	s.RegisterName("Home", new(home.HomeHandler), "")