Selaa lähdekoodia

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

wangxingcheng 3 vuotta sitten
vanhempi
commit
6b415b3ef3

+ 360 - 5
doc/订单全流程管理平台.pdma.json

@@ -2,9 +2,9 @@
   "name": "订单全流程管理平台",
   "describe": "订单全流程管理平台",
   "avatar": "",
-  "version": "4.2.2",
-  "createdTime": "2023-1-6 11:43:05",
-  "updatedTime": "2023-1-6 11:43:05",
+  "version": "4.1.1",
+  "createdTime": "2022-12-6 07:35:33",
+  "updatedTime": "2023-1-9 17:45:35",
   "dbConns": [],
   "profile": {
     "default": {
@@ -7093,7 +7093,7 @@
         },
         {
           "defKey": "appro_status",
-          "defName": "审核状态",
+          "defName": "审核状态 10 未通过 20 已通过",
           "comment": "",
           "type": "",
           "len": "",
@@ -13987,6 +13987,360 @@
       ],
       "correlations": [],
       "indexes": []
+    },
+    {
+      "id": "E5C3DA58-7436-45A1-87DE-284D7A724914",
+      "env": {
+        "base": {
+          "nameSpace": "",
+          "codeRoot": ""
+        }
+      },
+      "defKey": "ctr_contract_dynamics",
+      "defName": "合同动态",
+      "comment": "",
+      "properties": {
+        "partitioned by": "(date string)",
+        "row format delimited": "",
+        "fields terminated by ','": "",
+        "collection items terminated by '-'": "",
+        "map keys terminated by ':'": "",
+        "store as textfile;": ""
+      },
+      "nameTemplate": "{defKey}[{defName}]",
+      "headers": [
+        {
+          "refKey": "hideInGraph",
+          "hideInGraph": true
+        },
+        {
+          "refKey": "defKey",
+          "hideInGraph": false
+        },
+        {
+          "refKey": "defName",
+          "hideInGraph": false
+        },
+        {
+          "refKey": "primaryKey",
+          "hideInGraph": false
+        },
+        {
+          "refKey": "notNull",
+          "hideInGraph": true
+        },
+        {
+          "refKey": "autoIncrement",
+          "hideInGraph": true
+        },
+        {
+          "refKey": "domain",
+          "hideInGraph": true
+        },
+        {
+          "refKey": "type",
+          "hideInGraph": false
+        },
+        {
+          "refKey": "len",
+          "hideInGraph": false
+        },
+        {
+          "refKey": "scale",
+          "hideInGraph": false
+        },
+        {
+          "refKey": "comment",
+          "hideInGraph": true
+        },
+        {
+          "refKey": "refDict",
+          "hideInGraph": true
+        },
+        {
+          "refKey": "defaultValue",
+          "hideInGraph": true
+        },
+        {
+          "refKey": "isStandard",
+          "hideInGraph": false
+        },
+        {
+          "refKey": "uiHint",
+          "hideInGraph": true
+        },
+        {
+          "refKey": "extProps",
+          "hideInGraph": true
+        }
+      ],
+      "fields": [
+        {
+          "defKey": "id",
+          "defName": "主键",
+          "comment": "",
+          "type": "",
+          "len": "",
+          "scale": "",
+          "primaryKey": true,
+          "notNull": true,
+          "autoIncrement": true,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "refDict": "",
+          "extProps": {},
+          "domain": "6BC8F04B-6CFA-4995-98D3-318F5CDD774E",
+          "id": "C3445EE8-F606-4A60-8BB5-FB813C4E849D"
+        },
+        {
+          "defKey": "contract_id",
+          "defName": "合同ID",
+          "comment": "",
+          "type": "",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": true,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "refDict": "",
+          "extProps": {},
+          "domain": "6BC8F04B-6CFA-4995-98D3-318F5CDD774E",
+          "id": "2246B3FD-1EB8-4524-BD45-5B933E92B99A"
+        },
+        {
+          "defKey": "opn_people_id",
+          "defName": "操作人ID",
+          "comment": "",
+          "type": "",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": true,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "refDict": "",
+          "extProps": {},
+          "domain": "6BC8F04B-6CFA-4995-98D3-318F5CDD774E",
+          "id": "D0700CB7-BEB1-4CFE-9E34-D7642B436A7B"
+        },
+        {
+          "defKey": "opn_people",
+          "defName": "操作人",
+          "comment": "",
+          "type": "",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": true,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "refDict": "",
+          "extProps": {},
+          "domain": "54611CCC-CA4B-42E1-9F32-4944C85B85A6",
+          "id": "ED9F8436-05B2-445D-9FD8-536126DA5D45"
+        },
+        {
+          "defKey": "opn_date",
+          "defName": "操作日期",
+          "comment": "",
+          "type": "DATETIME",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": true,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "refDict": "",
+          "extProps": {},
+          "domain": "",
+          "id": "8D11CF9A-62FF-4A57-BEF6-D5E0B8073356"
+        },
+        {
+          "defKey": "opn_type",
+          "defName": "操作类型",
+          "comment": "",
+          "type": "",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": true,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "refDict": "",
+          "extProps": {},
+          "domain": "73FD2BAD-2358-4336-B96D-45DC897BD792",
+          "id": "F614873B-9C5A-404A-BA30-D2DCCC26BEB5"
+        },
+        {
+          "defKey": "opn_content",
+          "defName": "操作内容",
+          "comment": "",
+          "type": "",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": false,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "refDict": "",
+          "extProps": {},
+          "domain": "3E948CEC-3070-472C-AF92-F3CA11EC9D15",
+          "id": "5B1BAD05-DFB0-41AE-8C6A-A246C7C4F8EC"
+        },
+        {
+          "defKey": "remark",
+          "defName": "备注",
+          "comment": "",
+          "type": "",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": false,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "domain": "3E948CEC-3070-472C-AF92-F3CA11EC9D15",
+          "refDict": "",
+          "extProps": {},
+          "notes": {},
+          "id": "7880B3FA-ACAC-401C-AB1C-3304FE48E53B"
+        },
+        {
+          "defKey": "created_by",
+          "defName": "创建者",
+          "comment": "",
+          "type": "",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": true,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "domain": "16120F75-6AA7-4483-868D-F07F511BB081",
+          "refDict": "",
+          "extProps": {},
+          "notes": {},
+          "id": "EAEFDA42-550C-4EB5-9D32-03B446763F92"
+        },
+        {
+          "defKey": "created_name",
+          "defName": "创建人",
+          "comment": "",
+          "type": "VARCHAR",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": true,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "domain": "54611CCC-CA4B-42E1-9F32-4944C85B85A6",
+          "refDict": "",
+          "extProps": {},
+          "notes": {},
+          "id": "0B43210A-6ACE-45F6-8026-53256207CE0F"
+        },
+        {
+          "defKey": "created_time",
+          "defName": "创建时间",
+          "comment": "",
+          "type": "DATETIME",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": true,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "domain": "7CFFA0D3-6A93-4DDC-BC10-DF21211064DC",
+          "refDict": "",
+          "extProps": {},
+          "notes": {},
+          "id": "48B9A20C-F60E-412A-A359-D0EDD27BB98D"
+        },
+        {
+          "defKey": "updated_by",
+          "defName": "更新者",
+          "comment": "",
+          "type": "",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": false,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "domain": "16120F75-6AA7-4483-868D-F07F511BB081",
+          "refDict": "",
+          "extProps": {},
+          "notes": {},
+          "id": "E73FC6F3-A402-44BA-A9A0-1D753B4FBB3D"
+        },
+        {
+          "defKey": "updated_name",
+          "defName": "更新人",
+          "comment": "",
+          "type": "VARCHAR",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": false,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "domain": "54611CCC-CA4B-42E1-9F32-4944C85B85A6",
+          "refDict": "",
+          "extProps": {},
+          "notes": {},
+          "id": "A274F906-05A2-4E08-A019-A48F99EFEE6A"
+        },
+        {
+          "defKey": "updated_time",
+          "defName": "更新时间",
+          "comment": "",
+          "type": "DATETIME",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": false,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "domain": "7CFFA0D3-6A93-4DDC-BC10-DF21211064DC",
+          "refDict": "",
+          "extProps": {},
+          "notes": {},
+          "id": "BBC9ED1D-34F6-48ED-BF8B-8BB2812092D3"
+        },
+        {
+          "defKey": "deleted_time",
+          "defName": "删除时间",
+          "comment": "",
+          "type": "DATETIME",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": false,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "domain": "7CFFA0D3-6A93-4DDC-BC10-DF21211064DC",
+          "refDict": "",
+          "extProps": {},
+          "notes": {},
+          "id": "2E27E5A6-D66D-4ACC-B0C3-B38D1CCAA7DC"
+        }
+      ],
+      "correlations": [],
+      "indexes": []
     }
   ],
   "views": [],
@@ -14402,7 +14756,8 @@
         "6511F53F-57C6-4726-BA34-8C68EA8ECDA2",
         "403821BB-46D8-4AED-BAEF-E2BEF3C0EB60",
         "6C39B414-5E3A-4D0F-958F-19EDF97EA619",
-        "D01F5FE5-2704-464B-9268-9E4A22838D63"
+        "D01F5FE5-2704-464B-9268-9E4A22838D63",
+        "E5C3DA58-7436-45A1-87DE-284D7A724914"
       ],
       "refViews": [],
       "refDiagrams": [],

+ 36 - 0
opms_parent/app/dao/contract/ctr_contract_dynamics.go

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

+ 438 - 0
opms_parent/app/dao/contract/internal/ctr_contract_dynamics.go

@@ -0,0 +1,438 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"context"
+	"database/sql"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/frame/gmvc"
+	"time"
+
+	model "dashoo.cn/micro/app/model/contract"
+)
+
+// CtrContractDynamicsDao is the manager for logic model data accessing
+// and custom defined data operations functions management.
+type CtrContractDynamicsDao struct {
+	gmvc.M
+	DB      gdb.DB
+	Table   string
+	Columns ctrContractDynamicsColumns
+}
+
+// CtrContractDynamicsColumns defines and stores column names for table ctr_contract_dynamics.
+type ctrContractDynamicsColumns struct {
+	Id          string // 主键
+	ContractId  string // 合同ID
+	OpnPeopleId string // 操作人ID
+	OpnPeople   string // 操作人
+	OpnDate     string // 操作日期
+	OpnType     string // 操作类型
+	OpnContent  string // 操作内容
+	Remark      string // 备注
+	CreatedBy   string // 创建者
+	CreatedName string // 创建人
+	CreatedTime string // 创建时间
+	UpdatedBy   string // 更新者
+	UpdatedName string // 更新人
+	UpdatedTime string // 更新时间
+	DeletedTime string // 删除时间
+}
+
+var (
+	// CtrContractDynamics is globally public accessible object for table ctr_contract_dynamics operations.
+	CtrContractDynamics = CtrContractDynamicsDao{
+		M:     g.DB("default").Model("ctr_contract_dynamics").Safe(),
+		DB:    g.DB("default"),
+		Table: "ctr_contract_dynamics",
+		Columns: ctrContractDynamicsColumns{
+			Id:          "id",
+			ContractId:  "contract_id",
+			OpnPeopleId: "opn_people_id",
+			OpnPeople:   "opn_people",
+			OpnDate:     "opn_date",
+			OpnType:     "opn_type",
+			OpnContent:  "opn_content",
+			Remark:      "remark",
+			CreatedBy:   "created_by",
+			CreatedName: "created_name",
+			CreatedTime: "created_time",
+			UpdatedBy:   "updated_by",
+			UpdatedName: "updated_name",
+			UpdatedTime: "updated_time",
+			DeletedTime: "deleted_time",
+		},
+	}
+)
+
+func NewCtrContractDynamicsDao(tenant string) CtrContractDynamicsDao {
+	var dao CtrContractDynamicsDao
+	dao = CtrContractDynamicsDao{
+		M:     g.DB(tenant).Model("ctr_contract_dynamics").Safe(),
+		DB:    g.DB(tenant),
+		Table: "ctr_contract_dynamics",
+		Columns: ctrContractDynamicsColumns{
+			Id:          "id",
+			ContractId:  "contract_id",
+			OpnPeopleId: "opn_people_id",
+			OpnPeople:   "opn_people",
+			OpnDate:     "opn_date",
+			OpnType:     "opn_type",
+			OpnContent:  "opn_content",
+			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 *CtrContractDynamicsDao) Ctx(ctx context.Context) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Ctx(ctx)}
+}
+
+// As sets an alias name for current table.
+func (d *CtrContractDynamicsDao) As(as string) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.As(as)}
+}
+
+// TX sets the transaction for current operation.
+func (d *CtrContractDynamicsDao) TX(tx *gdb.TX) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.TX(tx)}
+}
+
+// Master marks the following operation on master node.
+func (d *CtrContractDynamicsDao) Master() *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Master()}
+}
+
+// Slave marks the following operation on slave node.
+// Note that it makes sense only if there's any slave node configured.
+func (d *CtrContractDynamicsDao) Slave() *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Slave()}
+}
+
+// Args sets custom arguments for model operation.
+func (d *CtrContractDynamicsDao) Args(args ...interface{}) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Args(args...)}
+}
+
+// LeftJoin does "LEFT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *CtrContractDynamicsDao) LeftJoin(table ...string) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.LeftJoin(table...)}
+}
+
+// RightJoin does "RIGHT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *CtrContractDynamicsDao) RightJoin(table ...string) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.RightJoin(table...)}
+}
+
+// InnerJoin does "INNER JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *CtrContractDynamicsDao) InnerJoin(table ...string) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.InnerJoin(table...)}
+}
+
+// Fields sets the operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *CtrContractDynamicsDao) Fields(fieldNamesOrMapStruct ...interface{}) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Fields(fieldNamesOrMapStruct...)}
+}
+
+// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *CtrContractDynamicsDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)}
+}
+
+// Option sets the extra operation option for the model.
+func (d *CtrContractDynamicsDao) Option(option int) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Option(option)}
+}
+
+// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers
+// the data and where attributes for empty values.
+func (d *CtrContractDynamicsDao) OmitEmpty() *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.OmitEmpty()}
+}
+
+// Filter marks filtering the fields which does not exist in the fields of the operated table.
+func (d *CtrContractDynamicsDao) Filter() *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Filter()}
+}
+
+// Where sets the condition statement for the model. The parameter <where> can be type of
+// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
+// multiple conditions will be joined into where statement using "AND".
+// Eg:
+// Where("uid=10000")
+// Where("uid", 10000)
+// Where("money>? AND name like ?", 99999, "vip_%")
+// Where("uid", 1).Where("name", "john")
+// Where("status IN (?)", g.Slice{1,2,3})
+// Where("age IN(?,?)", 18, 50)
+// Where(User{ Id : 1, UserName : "john"})
+func (d *CtrContractDynamicsDao) Where(where interface{}, args ...interface{}) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Where(where, args...)}
+}
+
+// WherePri does the same logic as M.Where except that if the parameter <where>
+// is a single condition like int/string/float/slice, it treats the condition as the primary
+// key value. That is, if primary key is "id" and given <where> parameter as "123", the
+// WherePri function treats the condition as "id=123", but M.Where treats the condition
+// as string "123".
+func (d *CtrContractDynamicsDao) WherePri(where interface{}, args ...interface{}) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.WherePri(where, args...)}
+}
+
+// And adds "AND" condition to the where statement.
+func (d *CtrContractDynamicsDao) And(where interface{}, args ...interface{}) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.And(where, args...)}
+}
+
+// Or adds "OR" condition to the where statement.
+func (d *CtrContractDynamicsDao) Or(where interface{}, args ...interface{}) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Or(where, args...)}
+}
+
+// Group sets the "GROUP BY" statement for the model.
+func (d *CtrContractDynamicsDao) Group(groupBy string) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Group(groupBy)}
+}
+
+// Order sets the "ORDER BY" statement for the model.
+func (d *CtrContractDynamicsDao) Order(orderBy ...string) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Order(orderBy...)}
+}
+
+// Limit sets the "LIMIT" statement for the model.
+// The parameter <limit> can be either one or two number, if passed two number is passed,
+// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
+// statement.
+func (d *CtrContractDynamicsDao) Limit(limit ...int) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Limit(limit...)}
+}
+
+// Offset sets the "OFFSET" statement for the model.
+// It only makes sense for some databases like SQLServer, PostgreSQL, etc.
+func (d *CtrContractDynamicsDao) Offset(offset int) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Offset(offset)}
+}
+
+// Page sets the paging number for the model.
+// The parameter <page> is started from 1 for paging.
+// Note that, it differs that the Limit function start from 0 for "LIMIT" statement.
+func (d *CtrContractDynamicsDao) Page(page, limit int) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Page(page, limit)}
+}
+
+// Batch sets the batch operation number for the model.
+func (d *CtrContractDynamicsDao) Batch(batch int) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Batch(batch)}
+}
+
+// Cache sets the cache feature for the model. It caches the result of the sql, which means
+// if there's another same sql request, it just reads and returns the result from cache, it
+// but not committed and executed into the database.
+//
+// If the parameter <duration> < 0, which means it clear the cache with given <name>.
+// If the parameter <duration> = 0, which means it never expires.
+// If the parameter <duration> > 0, which means it expires after <duration>.
+//
+// The optional parameter <name> is used to bind a name to the cache, which means you can later
+// control the cache like changing the <duration> or clearing the cache with specified <name>.
+//
+// Note that, the cache feature is disabled if the model is operating on a transaction.
+func (d *CtrContractDynamicsDao) Cache(duration time.Duration, name ...string) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Cache(duration, name...)}
+}
+
+// Data sets the operation data for the model.
+// The parameter <data> can be type of string/map/gmap/slice/struct/*struct, etc.
+// Eg:
+// Data("uid=10000")
+// Data("uid", 10000)
+// Data(g.Map{"uid": 10000, "name":"john"})
+// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
+func (d *CtrContractDynamicsDao) Data(data ...interface{}) *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Data(data...)}
+}
+
+// All does "SELECT FROM ..." statement for the model.
+// It retrieves the records from table and returns the result as []*model.CtrContractDynamics.
+// 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 *CtrContractDynamicsDao) All(where ...interface{}) ([]*model.CtrContractDynamics, error) {
+	all, err := d.M.All(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*model.CtrContractDynamics
+	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.CtrContractDynamics.
+// 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 *CtrContractDynamicsDao) One(where ...interface{}) (*model.CtrContractDynamics, error) {
+	one, err := d.M.One(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *model.CtrContractDynamics
+	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 *CtrContractDynamicsDao) FindOne(where ...interface{}) (*model.CtrContractDynamics, error) {
+	one, err := d.M.FindOne(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *model.CtrContractDynamics
+	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 *CtrContractDynamicsDao) FindAll(where ...interface{}) ([]*model.CtrContractDynamics, error) {
+	all, err := d.M.FindAll(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*model.CtrContractDynamics
+	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 *CtrContractDynamicsDao) 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 *CtrContractDynamicsDao) 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 *CtrContractDynamicsDao) Scan(pointer interface{}, where ...interface{}) error {
+	return d.M.Scan(pointer, where...)
+}
+
+// Chunk iterates the table with given size and callback function.
+func (d *CtrContractDynamicsDao) Chunk(limit int, callback func(entities []*model.CtrContractDynamics, err error) bool) {
+	d.M.Chunk(limit, func(result gdb.Result, err error) bool {
+		var entities []*model.CtrContractDynamics
+		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 *CtrContractDynamicsDao) LockUpdate() *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.LockUpdate()}
+}
+
+// LockShared sets the lock in share mode for current operation.
+func (d *CtrContractDynamicsDao) LockShared() *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.LockShared()}
+}
+
+// Unscoped enables/disables the soft deleting feature.
+func (d *CtrContractDynamicsDao) Unscoped() *CtrContractDynamicsDao {
+	return &CtrContractDynamicsDao{M: d.M.Unscoped()}
+}

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

@@ -52,6 +52,29 @@ func (c *CtrContract) List(ctx context.Context, req *model.CtrContractListReq, r
 	return nil
 }
 
+func (c *CtrContract) DynamicsList(ctx context.Context, req *model.CtrContractDynamicsListReq, rsp *comm_def.CommonMsg) error {
+	g.Log().Infof("CtrContract.DynamicsList request %#v ", *req)
+	s, err := service.NewCtrContractService(ctx)
+	if err != nil {
+		return err
+	}
+	total, ent, err := s.DynamicsList(ctx, req)
+	_, err, code, msg := myerrors.CheckError(err)
+	if err != nil {
+		return err
+	}
+	if ent == nil {
+		ent = []*model.CtrContract{}
+	}
+	rsp.Code = code
+	rsp.Msg = msg
+	rsp.Data = map[string]interface{}{
+		"total": total,
+		"list":  ent,
+	}
+	return nil
+}
+
 func (c *CtrContract) Add(ctx context.Context, req *model.CtrContractAddReq, rsp *comm_def.CommonMsg) error {
 	g.Log().Infof("CtrContract.Add request %#v ", *req)
 	s, err := service.NewCtrContractService(ctx)

+ 17 - 0
opms_parent/app/handler/contract/ctr_contract_collection_plan.go

@@ -12,6 +12,23 @@ import (
 
 type CtrContractCollectionPlan struct{}
 
+func (c *CtrContractCollectionPlan) Get(ctx context.Context, req *model.IdRequiredReq, rsp *comm_def.CommonMsg) error {
+	g.Log().Infof("CtrContractCollectionPlan.Get request %#v ", *req)
+	s, err := service.NewCtrContractCollectionPlanService(ctx)
+	if err != nil {
+		return err
+	}
+	ent, err := s.Get(ctx, req.Id)
+	_, err, code, msg := myerrors.CheckError(err)
+	if err != nil {
+		return err
+	}
+	rsp.Code = code
+	rsp.Msg = msg
+	rsp.Data = ent
+	return nil
+}
+
 func (c *CtrContractCollectionPlan) List(ctx context.Context, req *model.CtrContractCollectionPlanListReq, rsp *comm_def.CommonMsg) error {
 	g.Log().Infof("CtrContractCollectionPlan.List request %#v ", *req)
 	s, err := service.NewCtrContractCollectionPlanService(ctx)

+ 0 - 0
opms_parent/app/handler/contract/ctr_contract_invoice.go.bak → opms_parent/app/handler/contract/ctr_contract_invoice.go


+ 5 - 5
opms_parent/app/model/contract/ctr_contract_collection.go

@@ -25,7 +25,7 @@ type CtrContractCollectionListReq struct {
 	// CollectionDatetime *gtime.Time `json:"collectionDatetime"` // 回款日期
 	// CollectionAmount   float64     `json:"collectionAmount"`   // 回款金额
 	CollectionType string `json:"collectionType"` // 回款方式
-	// ApproStatus        string      `json:"approStatus"`        // 审核状态 10 未回款 20 已回款
+	ApproStatus    string `json:"approStatus"`    // 审核状态 10 未回款 20 已回款
 	// ContractAmount     float64     `json:"contractAmount"`     // 合同金额
 }
 
@@ -38,17 +38,17 @@ type CtrContractCollectionAddReq struct {
 	CollectionDatetime *gtime.Time `json:"collectionDatetime"` // 回款日期
 	CollectionAmount   float64     `json:"collectionAmount"`   // 回款金额
 	CollectionType     string      `json:"collectionType"`     // 回款方式
-	ApproStatus        string      `json:"approStatus"`        // 审核状态 10 未回款 20 已回款
+	// ApproStatus        string      `json:"approStatus"`        // 审核状态 10 未回款 20 已回款
 	// ContractAmount     float64     `json:"contractAmount"`     // 合同金额
 	Remark string `json:"remark"` // 备注
 }
 
 type CtrContractCollectionUpdateReq struct {
-	Id     int `json:"id" v:"required#请输入Id"`
-	PlanId int `json:"planId"` // 合同回款计划
+	Id int `json:"id" v:"required#请输入Id"`
+	// PlanId int `json:"planId"` // 合同回款计划
 	// CustId             int         `json:"custId"`             // 关联客户
 	// CustName           string      `json:"custName"`           // 客户名称
-	ContractId int `json:"contractId"` // 关联合同
+	// ContractId int `json:"contractId"` // 关联合同
 	// ContractCode       string      `json:"contractCode"`       // 合同编号
 	CollectionDatetime *gtime.Time `json:"collectionDatetime"` // 回款日期
 	CollectionAmount   *float64    `json:"collectionAmount"`   // 回款金额

+ 11 - 5
opms_parent/app/model/contract/ctr_contract_collection_plan.go

@@ -14,6 +14,12 @@ import (
 type CtrContractCollectionPlan internal.CtrContractCollectionPlan
 
 // Fill with you ideas below.
+
+type CtrContractCollectionPlanGetRsp struct {
+	CtrContractCollectionPlan
+	Collection []*CtrContractCollection `json:"collection"`
+}
+
 type CtrContractCollectionPlanListReq struct {
 	request.PageReq
 	SearchText     string `json:"searchText"`     // 合同编号,客户名称
@@ -34,11 +40,11 @@ type CtrContractCollectionPlanAddReq struct {
 	ContractId int `json:"contractId"` // 关联合同
 	// ContractCode   string      `json:"contractCode"`   // 合同编号
 	// ContractStatus string      `json:"contractStatus"` // 回款状态(10待回款20部分回款30全部回款)
-	PlanAmount     float64     `json:"planAmount"`     // 计划回款金额
-	PlanDatetime   *gtime.Time `json:"planDatetime"`   // 计划回款日期
-	CashedAmount   float64     `json:"cashedAmount"`   // 实际回款金额
-	CashedDatetime *gtime.Time `json:"cashedDatetime"` // 实际回款日期
-	Remark         string      `json:"remark"`         // 备注
+	PlanAmount   float64     `json:"planAmount"`   // 计划回款金额
+	PlanDatetime *gtime.Time `json:"planDatetime"` // 计划回款日期
+	// CashedAmount   float64     `json:"cashedAmount"`   // 实际回款金额
+	// CashedDatetime *gtime.Time `json:"cashedDatetime"` // 实际回款日期
+	Remark string `json:"remark"` // 备注
 }
 
 type CtrContractCollectionPlanUpdateReq struct {

+ 25 - 0
opms_parent/app/model/contract/ctr_contract_dynamics.go

@@ -0,0 +1,25 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. Fill this file as you wish.
+// ==========================================================================
+
+package contract
+
+import (
+	"dashoo.cn/micro/app/model/contract/internal"
+	"dashoo.cn/opms_libary/request"
+)
+
+// CtrContractDynamics is the golang structure for table ctr_contract_dynamics.
+type CtrContractDynamics internal.CtrContractDynamics
+
+// Fill with you ideas below.
+type CtrContractDynamicsListReq struct {
+	request.PageReq
+	SearchText  string `json:"searchText"`  // 操作人,操作内容
+	ContractId  int    `json:"contractId"`  // 合同ID
+	OpnPeopleId int    `json:"opnPeopleId"` // 操作人ID
+	OpnPeople   string `json:"opnPeople"`   // 操作人
+	// OpnDate     *gtime.Time `json:"opnDate"`     // 操作日期
+	OpnType string `json:"opnType"` // 操作类型
+	// OpnContent string `json:"opnContent"` // 操作内容
+}

+ 30 - 29
opms_parent/app/model/contract/ctr_contract_invoice.go

@@ -16,30 +16,31 @@ type CtrContractInvoice internal.CtrContractInvoice
 // Fill with you ideas below.
 type CtrContractInvoiceListReq struct {
 	request.PageReq
-	CustId            int         `json:"custId"`            // 关联客户
-	CustName          string      `json:"custName"`          // 客户名称
-	ContractId        int         `json:"contractId"`        // 关联合同
-	ContractCode      string      `json:"contractCode"`      // 合同编号
-	ContractAmount    float64     `json:"contractAmount"`    // 合同金额
-	InvoiceAmount     float64     `json:"invoiceAmount"`     // 开票金额
-	InvoiceDate       *gtime.Time `json:"invoiceDate"`       // 开票日期
-	InvoiceType       string      `json:"invoiceType"`       // 开票类型
-	ApproStatus       string      `json:"approStatus"`       // 审核状态
-	InvoiceCode       string      `json:"invoiceCode"`       // 发票号码
-	ActualInvoiceDate *gtime.Time `json:"actualInvoiceDate"` // 实际开票日期
-	CourierCode       string      `json:"courierCode"`       // 快递单号
+	SearchText   string `json:"searchText"`   // 合同编号,客户名称
+	CustId       int    `json:"custId"`       // 关联客户
+	CustName     string `json:"custName"`     // 客户名称
+	ContractId   int    `json:"contractId"`   // 关联合同
+	ContractCode string `json:"contractCode"` // 合同编号
+	// ContractAmount    float64     `json:"contractAmount"`    // 合同金额
+	// InvoiceAmount     float64     `json:"invoiceAmount"`     // 开票金额
+	// InvoiceDate       *gtime.Time `json:"invoiceDate"`       // 开票日期
+	InvoiceType string `json:"invoiceType"` // 开票类型
+	ApproStatus string `json:"approStatus"` // 审核状态 10 未通过 20 已通过
+	InvoiceCode string `json:"invoiceCode"` // 发票号码
+	// ActualInvoiceDate *gtime.Time `json:"actualInvoiceDate"` // 实际开票日期
+	CourierCode string `json:"courierCode"` // 快递单号
 }
 
 type CtrContractInvoiceAddReq struct {
-	CustId            int         `json:"custId"`            // 关联客户
-	CustName          string      `json:"custName"`          // 客户名称
-	ContractId        int         `json:"contractId"`        // 关联合同
-	ContractCode      string      `json:"contractCode"`      // 合同编号
-	ContractAmount    float64     `json:"contractAmount"`    // 合同金额
-	InvoiceAmount     float64     `json:"invoiceAmount"`     // 开票金额
-	InvoiceDate       *gtime.Time `json:"invoiceDate"`       // 开票日期
-	InvoiceType       string      `json:"invoiceType"`       // 开票类型
-	ApproStatus       string      `json:"approStatus"`       // 审核状态
+	// CustId            int         `json:"custId"`            // 关联客户
+	// CustName          string      `json:"custName"`          // 客户名称
+	ContractId int `json:"contractId"` // 关联合同
+	// ContractCode      string      `json:"contractCode"`      // 合同编号
+	// ContractAmount    float64     `json:"contractAmount"`    // 合同金额
+	InvoiceAmount float64     `json:"invoiceAmount"` // 开票金额
+	InvoiceDate   *gtime.Time `json:"invoiceDate"`   // 开票日期
+	InvoiceType   string      `json:"invoiceType"`   // 开票类型
+	// ApproStatus       string      `json:"approStatus"`       // 审核状态 10 未通过 20 已通过
 	InvoiceCode       string      `json:"invoiceCode"`       // 发票号码
 	ActualInvoiceDate *gtime.Time `json:"actualInvoiceDate"` // 实际开票日期
 	CourierCode       string      `json:"courierCode"`       // 快递单号
@@ -47,16 +48,16 @@ type CtrContractInvoiceAddReq struct {
 }
 
 type CtrContractInvoiceUpdateReq struct {
-	Id                int         `json:"id" v:"required#请输入Id"`
-	CustId            int         `json:"custId"`            // 关联客户
-	CustName          string      `json:"custName"`          // 客户名称
-	ContractId        int         `json:"contractId"`        // 关联合同
-	ContractCode      string      `json:"contractCode"`      // 合同编号
-	ContractAmount    float64     `json:"contractAmount"`    // 合同金额
-	InvoiceAmount     float64     `json:"invoiceAmount"`     // 开票金额
+	Id int `json:"id" v:"required#请输入Id"`
+	// CustId            int         `json:"custId"`            // 关联客户
+	// CustName          string      `json:"custName"`          // 客户名称
+	// ContractId        int         `json:"contractId"`        // 关联合同
+	// ContractCode      string      `json:"contractCode"`      // 合同编号
+	// ContractAmount    float64     `json:"contractAmount"`    // 合同金额
+	InvoiceAmount     *float64    `json:"invoiceAmount"`     // 开票金额
 	InvoiceDate       *gtime.Time `json:"invoiceDate"`       // 开票日期
 	InvoiceType       string      `json:"invoiceType"`       // 开票类型
-	ApproStatus       string      `json:"approStatus"`       // 审核状态
+	ApproStatus       string      `json:"approStatus"`       // 审核状态 10 未通过 20 已通过
 	InvoiceCode       string      `json:"invoiceCode"`       // 发票号码
 	ActualInvoiceDate *gtime.Time `json:"actualInvoiceDate"` // 实际开票日期
 	CourierCode       string      `json:"courierCode"`       // 快递单号

+ 28 - 0
opms_parent/app/model/contract/internal/ctr_contract_dynamics.go

@@ -0,0 +1,28 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"github.com/gogf/gf/os/gtime"
+)
+
+// CtrContractDynamics is the golang structure for table ctr_contract_dynamics.
+type CtrContractDynamics struct {
+	Id          int         `orm:"id,primary"    json:"id"`          // 主键
+	ContractId  int         `orm:"contract_id"   json:"contractId"`  // 合同ID
+	OpnPeopleId int         `orm:"opn_people_id" json:"opnPeopleId"` // 操作人ID
+	OpnPeople   string      `orm:"opn_people"    json:"opnPeople"`   // 操作人
+	OpnDate     *gtime.Time `orm:"opn_date"      json:"opnDate"`     // 操作日期
+	OpnType     string      `orm:"opn_type"      json:"opnType"`     // 操作类型
+	OpnContent  string      `orm:"opn_content"   json:"opnContent"`  // 操作内容
+	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"` // 删除时间
+}

+ 124 - 0
opms_parent/app/service/contract/ctr_contract.go

@@ -3,6 +3,7 @@ package service
 import (
 	"context"
 	"database/sql"
+	"encoding/json"
 	"fmt"
 
 	basedao "dashoo.cn/micro/app/dao/base"
@@ -28,6 +29,7 @@ type CtrContractService struct {
 	UserDao         *sysdao.SysUserDao
 	CtrProductDao   *dao.CtrContractProductDao
 	ProductDao      *basedao.BaseProductDao
+	DynamicsDao     *dao.CtrContractDynamicsDao
 
 	Tenant   string
 	userInfo request.UserInfo
@@ -50,6 +52,7 @@ func NewCtrContractService(ctx context.Context) (*CtrContractService, error) {
 		UserDao:         sysdao.NewSysUserDao(tenant),
 		CtrProductDao:   dao.NewCtrContractProductDao(tenant),
 		ProductDao:      basedao.NewBaseProductDao(tenant),
+		DynamicsDao:     dao.NewCtrContractDynamicsDao(tenant),
 		Tenant:          tenant,
 		userInfo:        userInfo,
 	}, nil
@@ -76,6 +79,63 @@ func (s CtrContractService) Get(ctx context.Context, id int) (*model.CtrContract
 	}, nil
 }
 
+func (s CtrContractService) DynamicsList(ctx context.Context, req *model.CtrContractDynamicsListReq) (int, interface{}, error) {
+	dao := &s.DynamicsDao.CtrContractDynamicsDao
+	if req.SearchText != "" {
+		likestr := fmt.Sprintf("%%%s%%", req.SearchText)
+		dao = dao.Where("(opn_people LIKE ? || opn_content LIKE ?)", likestr, likestr)
+	}
+	if req.ContractId != 0 {
+		dao = dao.Where("contract_id = ?", req.ContractId)
+	}
+	if req.OpnPeopleId != 0 {
+		dao = dao.Where("opn_people_id = ?", req.OpnPeopleId)
+	}
+	if req.OpnPeople != "" {
+		likestr := fmt.Sprintf("%%%s%%", req.OpnPeople)
+		dao = dao.Where("opn_people like ?", likestr)
+	}
+	if req.OpnType != "" {
+		dao = dao.Where("opn_type = ?", req.OpnType)
+	}
+	// if req.OpnContent != "" {
+	// 	likestr := fmt.Sprintf("%%%s%%", req.OpnContent)
+	// 	dao = dao.Where("opn_content like ?", likestr)
+	// }
+	if req.BeginTime != "" {
+		dao = dao.Where("created_time > ?", req.BeginTime)
+	}
+	if req.EndTime != "" {
+		dao = dao.Where("created_time < ?", req.EndTime)
+	}
+
+	total, err := dao.Count()
+	if err != nil {
+		return 0, nil, err
+	}
+	if req.PageNum != 0 {
+		dao = dao.Page(req.GetPage())
+	}
+	orderby := "created_time desc"
+	if req.OrderBy != "" {
+		orderby = req.OrderBy
+	}
+	dao = dao.Order(orderby)
+
+	ents := []*model.CtrContractDynamics{}
+	err = dao.Structs(&ents)
+	if err != nil && err != sql.ErrNoRows {
+		return 0, nil, err
+	}
+
+	ret := map[string][]*model.CtrContractDynamics{}
+	for _, ent := range ents {
+		date := ent.OpnDate.Format("Y-m-d")
+		ret[date] = append(ret[date], ent)
+	}
+	return total, ret, err
+}
+
 func (s CtrContractService) List(ctx context.Context, req *model.CtrContractListReq) (int, []*model.CtrContract, error) {
 	dao := &s.Dao.CtrContractDao
 	if req.SearchText != "" {
@@ -216,6 +276,29 @@ func (s CtrContractService) BindProduct(tx *gdb.TX, id int, product []model.CtrA
 	return nil
 }
 
+func (s CtrContractService) AddDynamicsByCurrentUser(tx *gdb.TX, contractId int, opnType string, content map[string]interface{}) error {
+	contentByte, err := json.Marshal(content)
+	if err != nil {
+		return err
+	}
+	_, err = tx.InsertAndGetId("ctr_contract_dynamics", model.CtrContractDynamics{
+		ContractId:  contractId,
+		OpnPeopleId: s.userInfo.Id,
+		OpnPeople:   s.userInfo.NickName,
+		OpnDate:     gtime.Now(),
+		OpnType:     opnType,
+		OpnContent:  string(contentByte),
+		Remark:      "",
+		CreatedBy:   s.userInfo.Id,
+		CreatedName: s.userInfo.NickName,
+		CreatedTime: gtime.Now(),
+		UpdatedBy:   s.userInfo.Id,
+		UpdatedName: s.userInfo.NickName,
+		UpdatedTime: gtime.Now(),
+	})
+	return err
+}
+
 func (s CtrContractService) Add(ctx context.Context, req *model.CtrContractAddReq) (int, error) {
 	validErr := gvalid.CheckStruct(ctx, req, nil)
 	if validErr != nil {
@@ -288,6 +371,10 @@ func (s CtrContractService) Add(ctx context.Context, req *model.CtrContractAddRe
 		if err != nil {
 			return err
 		}
+		err = s.AddDynamicsByCurrentUser(tx, int(ctrid), "创建合同", map[string]interface{}{})
+		if err != nil {
+			return err
+		}
 		id = int(ctrid)
 		return nil
 	})
@@ -443,6 +530,17 @@ func (s CtrContractService) Transfer(ctx context.Context, req *model.CtrContract
 		if err != nil {
 			return err
 		}
+		err = s.AddDynamicsByCurrentUser(tx, req.Id, "转移合同", map[string]interface{}{
+			"toInchargeId":     req.InchargeId,
+			"toInchargeName":   req.InchargeName,
+			"fromInchargeId":   ent.InchargeId,
+			"fromInchargeName": ent.InchargeName,
+			"operatedId":       s.userInfo.Id,
+			"operatedName":     s.userInfo.NickName,
+		})
+		if err != nil {
+			return err
+		}
 		return nil
 	})
 	if txerr != nil {
@@ -451,6 +549,32 @@ func (s CtrContractService) Transfer(ctx context.Context, req *model.CtrContract
 	return nil
 }
 
+func (s CtrContractService) UpdateInvoiceAmount(tx *gdb.TX, id int) error {
+	ctr := model.CtrContract{}
+	err := tx.GetStruct(&ctr, "select * from ctr_contract where id = ?", id)
+	if err == sql.ErrNoRows {
+		return myerrors.NewMsgError(err, fmt.Sprintf("合同不存在 %d", id))
+	}
+	if err != nil {
+		return err
+	}
+
+	v, err := tx.GetValue("select sum(invoice_amount) from ctr_contract_invoice where contract_id=? and appro_status='20' and deleted_time is null", id)
+	if err != nil {
+		return err
+	}
+	amount := v.Float64()
+
+	_, err = tx.Update("ctr_contract",
+		map[string]interface{}{
+			"invoice_amount": amount,
+		}, "id = ?", id)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
 func (s CtrContractService) UpdateCollectedAmount(tx *gdb.TX, id int) error {
 	ctr := model.CtrContract{}
 	err := tx.GetStruct(&ctr, "select * from ctr_contract where id = ?", id)

+ 32 - 8
opms_parent/app/service/contract/ctr_contract_append.go

@@ -2,14 +2,16 @@ package service
 
 import (
 	"context"
-	dao "dashoo.cn/micro/app/dao/contract"
-	model "dashoo.cn/micro/app/model/contract"
 	"database/sql"
 	"fmt"
 
+	dao "dashoo.cn/micro/app/dao/contract"
+	model "dashoo.cn/micro/app/model/contract"
+
 	"dashoo.cn/opms_libary/micro_srv"
 	"dashoo.cn/opms_libary/myerrors"
 	"dashoo.cn/opms_libary/request"
+	"github.com/gogf/gf/database/gdb"
 	"github.com/gogf/gf/os/gtime"
 	"github.com/gogf/gf/util/gvalid"
 )
@@ -17,6 +19,7 @@ import (
 type CtrContractAppendService struct {
 	Dao         *dao.CtrContractAppendDao
 	ContractDao *dao.CtrContractDao
+	ctrSrv      *CtrContractService
 	Tenant      string
 	userInfo    request.UserInfo
 }
@@ -31,9 +34,14 @@ func NewCtrContractAppendService(ctx context.Context) (*CtrContractAppendService
 	if err != nil {
 		return nil, fmt.Errorf("获取用户信息异常:%s", err.Error())
 	}
+	ctrSrv, err := NewCtrContractService(ctx)
+	if err != nil {
+		return nil, err
+	}
 	return &CtrContractAppendService{
 		Dao:         dao.NewCtrContractAppendDao(tenant),
 		ContractDao: dao.NewCtrContractDao(tenant),
+		ctrSrv:      ctrSrv,
 		Tenant:      tenant,
 		userInfo:    userInfo,
 	}, nil
@@ -90,7 +98,7 @@ func (s CtrContractAppendService) Add(ctx context.Context, req *model.CtrContrac
 		return 0, myerrors.NewMsgError(nil, fmt.Sprintf("合同不存在: %d", req.ContractId))
 	}
 
-	id, err := s.Dao.InsertAndGetId(model.CtrContractAppend{
+	contractAppend := model.CtrContractAppend{
 		ContractId:  req.ContractId,
 		FileName:    req.FileName,
 		FileType:    req.FileType,
@@ -103,11 +111,27 @@ func (s CtrContractAppendService) Add(ctx context.Context, req *model.CtrContrac
 		UpdatedName: s.userInfo.NickName,
 		UpdatedTime: gtime.Now(),
 		DeletedTime: gtime.Now(),
-	})
-	if err != nil {
-		return 0, err
 	}
-	return int(id), err
+
+	var id int
+	txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+		appendId, err := tx.InsertAndGetId("ctr_contract_append", contractAppend)
+		if err != nil {
+			return err
+		}
+		err = s.ctrSrv.AddDynamicsByCurrentUser(tx, int(req.ContractId), "创建合同附件", map[string]interface{}{
+			"id":       appendId,
+			"fileName": contractAppend.FileName,
+			"fileType": contractAppend.FileType,
+			"fileUrl":  contractAppend.FileUrl,
+		})
+		if err != nil {
+			return err
+		}
+		id = int(appendId)
+		return nil
+	})
+	return id, txerr
 }
 
 func (s CtrContractAppendService) Update(ctx context.Context, req *model.CtrContractAppendUpdateReq) error {
@@ -121,7 +145,7 @@ func (s CtrContractAppendService) Update(ctx context.Context, req *model.CtrCont
 		return err
 	}
 	if ent == nil {
-		return myerrors.NewMsgError(nil, fmt.Sprintf("文档不存在: %d", req.Id))
+		return myerrors.NewMsgError(nil, fmt.Sprintf("合同附件不存在: %d", req.Id))
 	}
 
 	if req.ContractId != 0 {

+ 44 - 26
opms_parent/app/service/contract/ctr_contract_collection.go

@@ -80,6 +80,9 @@ func (s CtrContractCollectionService) List(ctx context.Context, req *model.CtrCo
 	if req.CollectionType != "" {
 		dao = dao.Where("collection_type = ?", req.CollectionType)
 	}
+	if req.ApproStatus != "" {
+		dao = dao.Where("appro_status = ?", req.ApproStatus)
+	}
 	if req.BeginTime != "" {
 		dao = dao.Where("created_time > ?", req.BeginTime)
 	}
@@ -122,7 +125,7 @@ func (s CtrContractCollectionService) Add(ctx context.Context, req *model.CtrCon
 		return 0, myerrors.NewMsgError(nil, fmt.Sprintf("合同:%d 不存在", req.ContractId))
 	}
 
-	id, err := s.Dao.InsertAndGetId(model.CtrContractCollection{
+	ent := model.CtrContractCollection{
 		PlanId:             req.PlanId,
 		CustId:             c.CustId,
 		CustName:           c.CustName,
@@ -131,7 +134,7 @@ func (s CtrContractCollectionService) Add(ctx context.Context, req *model.CtrCon
 		CollectionDatetime: req.CollectionDatetime,
 		CollectionAmount:   req.CollectionAmount,
 		CollectionType:     req.CollectionType,
-		ApproStatus:        req.ApproStatus,
+		ApproStatus:        "10",
 		ContractAmount:     c.ContractAmount,
 		Remark:             req.Remark,
 		CreatedBy:          s.userInfo.Id,
@@ -141,11 +144,26 @@ func (s CtrContractCollectionService) Add(ctx context.Context, req *model.CtrCon
 		UpdatedName:        s.userInfo.NickName,
 		UpdatedTime:        gtime.Now(),
 		DeletedTime:        gtime.Now(),
-	})
-	if err != nil {
-		return 0, err
 	}
-	return int(id), err
+	var id int
+	txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+		collectionId, err := tx.InsertAndGetId("ctr_contract_collection", ent)
+		if err != nil {
+			return err
+		}
+		err = s.ctrSrv.AddDynamicsByCurrentUser(tx, req.ContractId, "创建回款", map[string]interface{}{
+			"id":                 collectionId,
+			"collectionDatetime": req.CollectionDatetime,
+			"collectionAmount":   req.CollectionAmount,
+			"collectionType":     req.CollectionType,
+		})
+		if err != nil {
+			return err
+		}
+		id = int(collectionId)
+		return nil
+	})
+	return id, txerr
 }
 
 func (s CtrContractCollectionService) UpdateAmount(tx *gdb.TX, id int) error {
@@ -181,28 +199,28 @@ func (s CtrContractCollectionService) Update(ctx context.Context, req *model.Ctr
 		return myerrors.NewMsgError(nil, fmt.Sprintf("回款:%d 不存在", req.Id))
 	}
 
-	var c *model.CtrContract
-	if req.ContractId != 0 {
-		c, err = s.ContractDao.Where("id = ?", req.ContractId).One()
-		if err != nil {
-			return err
-		}
-		if c == nil {
-			return myerrors.NewMsgError(nil, fmt.Sprintf("合同:%d 不存在", req.ContractId))
-		}
-	}
+	// var c *model.CtrContract
+	// if req.ContractId != 0 {
+	// 	c, err = s.ContractDao.Where("id = ?", req.ContractId).One()
+	// 	if err != nil {
+	// 		return err
+	// 	}
+	// 	if c == nil {
+	// 		return myerrors.NewMsgError(nil, fmt.Sprintf("合同:%d 不存在", req.ContractId))
+	// 	}
+	// }
 
 	toupdate := map[string]interface{}{}
-	if req.PlanId != 0 {
-		toupdate["plan_id"] = req.PlanId
-	}
-	if req.ContractId != 0 {
-		toupdate["cust_id"] = c.CustId
-		toupdate["cust_name"] = c.CustName
-		toupdate["contract_id"] = req.ContractId
-		toupdate["contract_code"] = c.ContractCode
-		toupdate["contract_amount"] = c.ContractAmount
-	}
+	// if req.PlanId != 0 {
+	// 	toupdate["plan_id"] = req.PlanId
+	// }
+	// if req.ContractId != 0 {
+	// 	toupdate["cust_id"] = c.CustId
+	// 	toupdate["cust_name"] = c.CustName
+	// 	toupdate["contract_id"] = req.ContractId
+	// 	toupdate["contract_code"] = c.ContractCode
+	// 	toupdate["contract_amount"] = c.ContractAmount
+	// }
 	if req.CollectionDatetime != nil {
 		toupdate["collection_datetime"] = req.CollectionDatetime
 	}

+ 53 - 15
opms_parent/app/service/contract/ctr_contract_collection_plan.go

@@ -17,9 +17,10 @@ import (
 )
 
 type CtrContractCollectionPlanService struct {
-	Dao         *dao.CtrContractCollectionPlanDao
-	ContractDao *dao.CtrContractDao
-	ctrSrv      *CtrContractService
+	Dao           *dao.CtrContractCollectionPlanDao
+	CollectionDao *dao.CtrContractCollectionDao
+	ContractDao   *dao.CtrContractDao
+	ctrSrv        *CtrContractService
 
 	Tenant   string
 	userInfo request.UserInfo
@@ -40,11 +41,33 @@ func NewCtrContractCollectionPlanService(ctx context.Context) (*CtrContractColle
 		return nil, err
 	}
 	return &CtrContractCollectionPlanService{
-		Dao:         dao.NewCtrContractCollectionPlanDao(tenant),
-		ContractDao: dao.NewCtrContractDao(tenant),
-		ctrSrv:      ctrSrv,
-		Tenant:      tenant,
-		userInfo:    userInfo,
+		Dao:           dao.NewCtrContractCollectionPlanDao(tenant),
+		ContractDao:   dao.NewCtrContractDao(tenant),
+		CollectionDao: dao.NewCtrContractCollectionDao(tenant),
+		ctrSrv:        ctrSrv,
+		Tenant:        tenant,
+		userInfo:      userInfo,
+	}, nil
+}
+
+func (s CtrContractCollectionPlanService) Get(ctx context.Context, id int) (*model.CtrContractCollectionPlanGetRsp, error) {
+	ent, err := s.Dao.Where("Id = ?", id).One()
+	if err != nil {
+		return nil, err
+	}
+	if ent == nil {
+		return nil, myerrors.NewMsgError(nil, "回款计划不存在")
+	}
+	c, err := s.CollectionDao.Where("plan_id = ?", id).All()
+	if err != nil {
+		return nil, err
+	}
+	if c == nil {
+		c = []*model.CtrContractCollection{}
+	}
+	return &model.CtrContractCollectionPlanGetRsp{
+		CtrContractCollectionPlan: *ent,
+		Collection:                c,
 	}, nil
 }
 
@@ -113,7 +136,7 @@ func (s CtrContractCollectionPlanService) Add(ctx context.Context, req *model.Ct
 		return 0, myerrors.NewMsgError(nil, fmt.Sprintf("合同:%d 不存在", req.ContractId))
 	}
 
-	id, err := s.Dao.InsertAndGetId(model.CtrContractCollectionPlan{
+	ent := model.CtrContractCollectionPlan{
 		CustId:         c.CustId,
 		CustName:       c.CustName,
 		ContractId:     req.ContractId,
@@ -121,8 +144,8 @@ func (s CtrContractCollectionPlanService) Add(ctx context.Context, req *model.Ct
 		ContractStatus: "10",
 		PlanAmount:     req.PlanAmount,
 		PlanDatetime:   req.PlanDatetime,
-		CashedAmount:   req.CashedAmount,
-		CashedDatetime: req.CashedDatetime,
+		CashedAmount:   0,
+		CashedDatetime: nil,
 		Remark:         req.Remark,
 		CreatedBy:      s.userInfo.Id,
 		CreatedName:    s.userInfo.NickName,
@@ -131,11 +154,26 @@ func (s CtrContractCollectionPlanService) Add(ctx context.Context, req *model.Ct
 		UpdatedName:    s.userInfo.NickName,
 		UpdatedTime:    gtime.Now(),
 		DeletedTime:    gtime.Now(),
-	})
-	if err != nil {
-		return 0, err
 	}
-	return int(id), err
+
+	var id int
+	txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+		planid, err := tx.InsertAndGetId("ctr_contract_collection_plan", ent)
+		if err != nil {
+			return err
+		}
+		err = s.ctrSrv.AddDynamicsByCurrentUser(tx, req.ContractId, "创建回款计划", map[string]interface{}{
+			"id":           planid,
+			"planAmount":   req.PlanAmount,
+			"planDatetime": req.PlanDatetime,
+		})
+		if err != nil {
+			return err
+		}
+		id = int(planid)
+		return nil
+	})
+	return id, txerr
 }
 
 func (s CtrContractCollectionPlanService) Update(ctx context.Context, req *model.CtrContractCollectionPlanUpdateReq) error {

+ 321 - 0
opms_parent/app/service/contract/ctr_contract_invoice.go

@@ -0,0 +1,321 @@
+package service
+
+import (
+	"context"
+	"database/sql"
+	"fmt"
+
+	dao "dashoo.cn/micro/app/dao/contract"
+	model "dashoo.cn/micro/app/model/contract"
+
+	"dashoo.cn/opms_libary/micro_srv"
+	"dashoo.cn/opms_libary/myerrors"
+	"dashoo.cn/opms_libary/request"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/os/gtime"
+	"github.com/gogf/gf/util/gvalid"
+)
+
+type CtrContractInvoiceService struct {
+	Dao         *dao.CtrContractInvoiceDao
+	ContractDao *dao.CtrContractDao
+	ctrSrv      *CtrContractService
+	Tenant      string
+	userInfo    request.UserInfo
+}
+
+func NewCtrContractInvoiceService(ctx context.Context) (*CtrContractInvoiceService, error) {
+	tenant, err := micro_srv.GetTenant(ctx)
+	if err != nil {
+		return nil, fmt.Errorf("获取组合码异常:%s", err.Error())
+	}
+	// 获取用户信息
+	userInfo, err := micro_srv.GetUserInfo(ctx)
+	if err != nil {
+		return nil, fmt.Errorf("获取用户信息异常:%s", err.Error())
+	}
+	ctrSrv, err := NewCtrContractService(ctx)
+	if err != nil {
+		return nil, err
+	}
+	return &CtrContractInvoiceService{
+		Dao:         dao.NewCtrContractInvoiceDao(tenant),
+		ContractDao: dao.NewCtrContractDao(tenant),
+		ctrSrv:      ctrSrv,
+		Tenant:      tenant,
+		userInfo:    userInfo,
+	}, nil
+}
+
+func (s CtrContractInvoiceService) List(ctx context.Context, req *model.CtrContractInvoiceListReq) (int, []*model.CtrContractInvoice, error) {
+	dao := &s.Dao.CtrContractInvoiceDao
+	if req.SearchText != "" {
+		likestr := fmt.Sprintf("%%%s%%", req.SearchText)
+		dao = dao.Where("(cust_name LIKE ? || contract_code LIKE ?)", likestr, likestr)
+	}
+	if req.CustId != 0 {
+		dao = dao.Where("cust_id = ?", req.CustId)
+	}
+	if req.CustName != "" {
+		likestr := fmt.Sprintf("%%%s%%", req.CustName)
+		dao = dao.Where("cust_name like ?", likestr)
+	}
+	if req.ContractId != 0 {
+		dao = dao.Where("contract_id = ?", req.ContractId)
+	}
+	if req.ContractCode != "" {
+		likestr := fmt.Sprintf("%%%s%%", req.ContractCode)
+		dao = dao.Where("contract_code like ?", likestr)
+	}
+	if req.InvoiceType != "" {
+		dao = dao.Where("invoice_type = ?", req.InvoiceType)
+	}
+	if req.ApproStatus != "" {
+		dao = dao.Where("appro_status = ?", req.ApproStatus)
+	}
+	if req.InvoiceCode != "" {
+		dao = dao.Where("invoice_code = ?", req.InvoiceCode)
+	}
+	if req.CourierCode != "" {
+		dao = dao.Where("courier_code = ?", req.CourierCode)
+	}
+
+	if req.BeginTime != "" {
+		dao = dao.Where("created_time > ?", req.BeginTime)
+	}
+	if req.EndTime != "" {
+		dao = dao.Where("created_time < ?", req.EndTime)
+	}
+
+	total, err := dao.Count()
+	if err != nil {
+		return 0, nil, err
+	}
+	if req.PageNum != 0 {
+		dao = dao.Page(req.GetPage())
+	}
+	orderby := "created_time desc"
+	if req.OrderBy != "" {
+		orderby = req.OrderBy
+	}
+	dao = dao.Order(orderby)
+
+	ents := []*model.CtrContractInvoice{}
+	err = dao.Structs(&ents)
+	if err != nil && err != sql.ErrNoRows {
+		return 0, nil, err
+	}
+	return total, ents, err
+}
+
+func (s CtrContractInvoiceService) Add(ctx context.Context, req *model.CtrContractInvoiceAddReq) (int, error) {
+	validErr := gvalid.CheckStruct(ctx, req, nil)
+	if validErr != nil {
+		return 0, myerrors.NewMsgError(nil, validErr.Current().Error())
+	}
+
+	c, err := s.ContractDao.Where("id = ?", req.ContractId).One()
+	if err != nil {
+		return 0, err
+	}
+	if c == nil {
+		return 0, myerrors.NewMsgError(nil, fmt.Sprintf("合同:%d 不存在", req.ContractId))
+	}
+
+	if req.InvoiceCode != "" {
+		ent, err := s.Dao.Where("invoice_code = ?", req.InvoiceCode).One()
+		if err != nil {
+			return 0, err
+		}
+		if ent != nil {
+			return 0, myerrors.NewMsgError(nil, fmt.Sprintf("发票号码:%s 已存在", req.InvoiceCode))
+		}
+	}
+	if req.CourierCode != "" {
+		ent, err := s.Dao.Where("courier_code = ?", req.CourierCode).One()
+		if err != nil {
+			return 0, err
+		}
+		if ent != nil {
+			return 0, myerrors.NewMsgError(nil, fmt.Sprintf("快递单号:%s 已存在", req.CourierCode))
+		}
+	}
+
+	ent := model.CtrContractInvoice{
+		CustId:            c.CustId,
+		CustName:          c.CustName,
+		ContractId:        req.ContractId,
+		ContractCode:      c.ContractCode,
+		ContractAmount:    c.ContractAmount,
+		InvoiceAmount:     req.InvoiceAmount,
+		InvoiceDate:       req.InvoiceDate,
+		InvoiceType:       req.InvoiceType,
+		ApproStatus:       "10",
+		InvoiceCode:       req.InvoiceCode,
+		ActualInvoiceDate: req.ActualInvoiceDate,
+		CourierCode:       req.CourierCode,
+		Remark:            req.Remark,
+		CreatedBy:         int(s.userInfo.Id),
+		CreatedName:       s.userInfo.NickName,
+		CreatedTime:       gtime.Now(),
+		UpdatedBy:         int(s.userInfo.Id),
+		UpdatedName:       s.userInfo.NickName,
+		UpdatedTime:       gtime.Now(),
+		DeletedTime:       gtime.Now(),
+	}
+	var id int
+	txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+		invoiceId, err := tx.InsertAndGetId("ctr_contract_invoice", ent)
+		if err != nil {
+			return err
+		}
+		err = s.ctrSrv.AddDynamicsByCurrentUser(tx, req.ContractId, "创建发票", map[string]interface{}{
+			"id":                invoiceId,
+			"invoiceAmount":     req.InvoiceAmount,
+			"invoiceDate":       req.InvoiceDate,
+			"invoiceType":       req.InvoiceType,
+			"invoiceCode":       req.InvoiceCode,
+			"actualInvoiceDate": req.ActualInvoiceDate,
+			"courierCode":       req.CourierCode,
+		})
+		if err != nil {
+			return err
+		}
+		id = int(invoiceId)
+		return nil
+	})
+	return id, txerr
+}
+
+func (s CtrContractInvoiceService) Update(ctx context.Context, req *model.CtrContractInvoiceUpdateReq) error {
+	validErr := gvalid.CheckStruct(ctx, req, nil)
+	if validErr != nil {
+		return myerrors.NewMsgError(nil, validErr.Current().Error())
+	}
+
+	ent, err := s.Dao.Where("id = ?", req.Id).One()
+	if err != nil {
+		return err
+	}
+	if ent == nil {
+		return myerrors.NewMsgError(nil, fmt.Sprintf("发票不存在: %d", req.Id))
+	}
+
+	if req.InvoiceCode != "" {
+		exist, err := s.Dao.Where("invoice_code = ?", req.InvoiceCode).One()
+		if err != nil {
+			return err
+		}
+		if exist != nil && exist.Id != req.Id {
+			return myerrors.NewMsgError(nil, fmt.Sprintf("发票号码: %s 已存在", req.InvoiceCode))
+		}
+	}
+	if req.CourierCode != "" {
+		exist, err := s.Dao.Where("courier_code = ?", req.CourierCode).One()
+		if err != nil {
+			return err
+		}
+		if exist != nil && exist.Id != req.Id {
+			return myerrors.NewMsgError(nil, fmt.Sprintf("快递单号: %s 已存在", req.CourierCode))
+		}
+	}
+
+	toupdate := map[string]interface{}{}
+	// if req.CustId != 0 {
+	// 	toupdate["cust_id"] = req.CustId
+	// }
+	// if req.CustName != 0 {
+	// 	toupdate["cust_name"] = req.CustName
+	// }
+	// if req.ContractId != 0 {
+	// 	toupdate["contract_id"] = req.ContractId
+	// }
+	// if req.ContractCode != 0 {
+	// 	toupdate["contract_code"] = req.ContractCode
+	// }
+	// if req.ContractAmount != 0 {
+	// 	toupdate["contract_amount"] = req.ContractAmount
+	// }
+	if req.InvoiceAmount != nil {
+		toupdate["invoice_amount"] = *req.InvoiceAmount
+	}
+	if req.InvoiceDate != nil {
+		toupdate["invoice_date"] = req.InvoiceDate
+	}
+	if req.InvoiceType != "" {
+		toupdate["invoice_type"] = req.InvoiceType
+	}
+	if req.ApproStatus != "" {
+		toupdate["appro_status"] = req.ApproStatus
+	}
+	if req.InvoiceCode != "" {
+		toupdate["invoice_code"] = req.InvoiceCode
+	}
+	if req.ActualInvoiceDate != nil {
+		toupdate["actual_invoice_date"] = req.ActualInvoiceDate
+	}
+	if req.CourierCode != "" {
+		toupdate["courier_code"] = req.CourierCode
+	}
+	if req.Remark != nil {
+		toupdate["remark"] = *req.Remark
+	}
+	if len(toupdate) != 0 {
+		toupdate["updated_by"] = int(s.userInfo.Id)
+		toupdate["updated_name"] = s.userInfo.NickName
+		toupdate["updated_time"] = gtime.Now()
+
+		txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+			_, err = tx.Update("ctr_contract_invoice", toupdate, "id= ?", req.Id)
+			if err != nil {
+				return err
+			}
+			if req.InvoiceAmount != nil || req.ApproStatus != "" {
+				err = s.ctrSrv.UpdateInvoiceAmount(tx, ent.ContractId)
+				if err != nil {
+					return err
+				}
+			}
+			return nil
+		})
+		if txerr != nil {
+			return txerr
+		}
+	}
+	return nil
+}
+
+func (s CtrContractInvoiceService) Delete(ctx context.Context, id []int) error {
+	if len(id) == 0 {
+		return nil
+	}
+	return s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+		contractId := map[int]bool{}
+		for _, i := range id {
+			ent := model.CtrContractInvoice{}
+			err := tx.GetStruct(&ent, "select * from ctr_contract_invoice where id = ?", i)
+			if err == sql.ErrNoRows {
+				continue
+			}
+			if err != nil {
+				return err
+			}
+			if ent.ApproStatus != "20" {
+				continue
+			}
+			contractId[ent.ContractId] = true
+		}
+
+		_, err := tx.Delete("ctr_contract_invoice", "id in (?)", id)
+		if err != nil {
+			return err
+		}
+		for cid := range contractId {
+			err = s.ctrSrv.UpdateInvoiceAmount(tx, cid)
+			if err != nil {
+				return err
+			}
+		}
+		return nil
+	})
+}

+ 0 - 212
opms_parent/app/service/contract/ctr_contract_invoice.go.bak

@@ -1,212 +0,0 @@
-package service
-
-import (
-	"context"
-	dao "dashoo.cn/micro/app/dao/contract"
-	model "dashoo.cn/micro/app/model/contract"
-	"database/sql"
-	"fmt"
-
-	"dashoo.cn/opms_libary/micro_srv"
-	"dashoo.cn/opms_libary/myerrors"
-	"dashoo.cn/opms_libary/request"
-	"github.com/gogf/gf/os/gtime"
-	"github.com/gogf/gf/util/gvalid"
-)
-
-type CtrContractInvoiceService struct {
-	Dao      *dao.CtrContractInvoiceDao
-	Tenant   string
-	userInfo request.UserInfo
-}
-
-func NewCtrContractInvoiceService(ctx context.Context) (*CtrContractInvoiceService, error) {
-	tenant, err := micro_srv.GetTenant(ctx)
-	if err != nil {
-		return nil, fmt.Errorf("获取组合码异常:%s", err.Error())
-	}
-	// 获取用户信息
-	userInfo, err := micro_srv.GetUserInfo(ctx)
-	if err != nil {
-		return nil, fmt.Errorf("获取用户信息异常:%s", err.Error())
-	}
-	return &CtrContractInvoiceService{
-		Dao:      dao.NewCtrContractInvoiceDao(tenant),
-		Tenant:   tenant,
-		userInfo: userInfo,
-	}, nil
-}
-
-func (s CtrContractInvoiceService) List(ctx context.Context, req *model.CtrContractInvoiceListReq) (int, []*model.CtrContractInvoice, error) {
-	dao := &s.Dao.CtrContractInvoiceDao
-	if req.SearchText != "" {
-		likestr := fmt.Sprintf("%%%s%%", req.SearchText)
-		dao = dao.Where("(doc_code LIKE ? || doc_name LIKE ?)", likestr, likestr)
-	}
-	if req.DocType != "" {
-		dao = dao.Where("doc_type = ?", req.DocType)
-	}
-
-	total, err := dao.Count()
-	if err != nil {
-		return 0, nil, err
-	}
-
-	if req.Page != nil {
-		if req.Page.Current == 0 {
-			req.Page.Current = 1
-		}
-		if req.Page.Size == 0 {
-			req.Page.Size = 10
-		}
-		dao = dao.Page(req.Page.Current, req.Page.Size)
-	}
-	if req.OrderBy == nil {
-		req.OrderBy = &model.OrderBy{}
-	}
-	if req.OrderBy.Value == "" {
-		req.OrderBy.Value = "created_time"
-		req.OrderBy.Type = "desc"
-	}
-	if req.OrderBy != nil && req.OrderBy.Value != "" {
-		order := "asc"
-		if req.OrderBy.Type == "desc" {
-			order = "desc"
-		}
-		dao = dao.Order(req.OrderBy.Value, order)
-	}
-
-	ents := []*model.CtrContractInvoice{}
-	err = dao.Structs(&ents)
-	if err != nil && err != sql.ErrNoRows {
-		return 0, nil, err
-	}
-	return total, ents, err
-}
-
-func (s CtrContractInvoiceService) Add(ctx context.Context, req *model.CtrContractInvoiceAddReq) (int, error) {
-	validErr := gvalid.CheckStruct(ctx, req, nil)
-	if validErr != nil {
-		return 0, myerrors.NewMsgError(nil, validErr.Current().Error())
-	}
-
-	t, err := s.Dao.Where("doc_code = ?", req.DocCode).One()
-	if err != nil {
-		return 0, err
-	}
-	if t != nil {
-		return 0, myerrors.NewMsgError(nil, fmt.Sprintf("文档编码:%s 已存在", req.DocCode))
-	}
-
-	id, err := s.Dao.InsertAndGetId(model.CtrContractInvoice{
-		CustId:            req.CustId,
-		CustName:          req.CustName,
-		ContractId:        req.ContractId,
-		ContractCode:      req.ContractCode,
-		ContractAmount:    req.ContractAmount,
-		InvoiceAmount:     req.InvoiceAmount,
-		InvoiceDate:       req.InvoiceDate,
-		InvoiceType:       req.InvoiceType,
-		ApproStatus:       req.ApproStatus,
-		InvoiceCode:       req.InvoiceCode,
-		ActualInvoiceDate: req.ActualInvoiceDate,
-		CourierCode:       req.CourierCode,
-		Remark:            req.Remark,
-		CreatedBy:         int(s.userInfo.Id),
-		CreatedName:       s.userInfo.NickName,
-		CreatedTime:       gtime.Now(),
-		UpdatedBy:         int(s.userInfo.Id),
-		UpdatedName:       s.userInfo.NickName,
-		UpdatedTime:       gtime.Now(),
-		DeletedTime:       gtime.Now(),
-	})
-	if err != nil {
-		return 0, err
-	}
-	return int(id), err
-}
-
-func (s CtrContractInvoiceService) Update(ctx context.Context, req *model.CtrContractInvoiceUpdateReq) error {
-	validErr := gvalid.CheckStruct(ctx, req, nil)
-	if validErr != nil {
-		return myerrors.NewMsgError(nil, validErr.Current().Error())
-	}
-
-	ent, err := s.Dao.Where("id = ?", req.Id).One()
-	if err != nil {
-		return err
-	}
-	if ent == nil {
-		return myerrors.NewMsgError(nil, fmt.Sprintf("文档不存在: %d", req.Id))
-	}
-
-	if req.DocCode != "" {
-		exist, err := s.Dao.Where("doc_code = ?", req.DocCode).One()
-		if err != nil {
-			return err
-		}
-		if exist != nil && exist.Id != req.Id {
-			return myerrors.NewMsgError(nil, fmt.Sprintf("文档编码: %s 已存在", req.DocCode))
-		}
-	}
-
-	dao := &s.Dao.CtrContractInvoiceDao
-	toupdate := map[string]interface{}{}
-	if req.CustId != 0 {
-		toupdate["cust_id"] = req.CustId
-	}
-	if req.CustName != 0 {
-		toupdate["cust_name"] = req.CustName
-	}
-	if req.ContractId != 0 {
-		toupdate["contract_id"] = req.ContractId
-	}
-	if req.ContractCode != 0 {
-		toupdate["contract_code"] = req.ContractCode
-	}
-	if req.ContractAmount != 0 {
-		toupdate["contract_amount"] = req.ContractAmount
-	}
-	if req.InvoiceAmount != 0 {
-		toupdate["invoice_amount"] = req.InvoiceAmount
-	}
-	if req.InvoiceDate != 0 {
-		toupdate["invoice_date"] = req.InvoiceDate
-	}
-	if req.InvoiceType != 0 {
-		toupdate["invoice_type"] = req.InvoiceType
-	}
-	if req.ApproStatus != 0 {
-		toupdate["appro_status"] = req.ApproStatus
-	}
-	if req.InvoiceCode != 0 {
-		toupdate["invoice_code"] = req.InvoiceCode
-	}
-	if req.ActualInvoiceDate != 0 {
-		toupdate["actual_invoice_date"] = req.ActualInvoiceDate
-	}
-	if req.CourierCode != 0 {
-		toupdate["courier_code"] = req.CourierCode
-	}
-	if req.Remark != nil {
-		toupdate["remark"] = *req.Remark
-	}
-	if len(toupdate) != 0 {
-		toupdate["updated_by"] = int(s.userInfo.Id)
-		toupdate["updated_name"] = s.userInfo.NickName
-		toupdate["updated_time"] = gtime.Now()
-		_, err = dao.Where("Id", req.Id).Data(toupdate).Update()
-		if err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func (s CtrContractInvoiceService) Delete(ctx context.Context, id []int) error {
-	if len(id) == 0 {
-		return nil
-	}
-	_, err := s.Dao.Where("Id  IN (?)", id).Delete()
-	return err
-}

+ 4 - 0
opms_parent/main.go

@@ -44,6 +44,10 @@ func main() {
 	s.RegisterName("BusinessFile", new(projHandler.BusinessFileHandler), "")
 	s.RegisterName("BusinessTeam", new(projHandler.BusinessTeamHandler), "")
 	s.RegisterName("CtrContract", new(contract.CtrContract), "")
+	s.RegisterName("CtrContractCollectionPlan", new(contract.CtrContractCollectionPlan), "")
+	s.RegisterName("CtrContractCollection", new(contract.CtrContractCollection), "")
+	s.RegisterName("CtrContractAppend", new(contract.CtrContractAppend), "")
+	s.RegisterName("CtrContractInvoice", new(contract.CtrContractInvoice), "")
 
 	// 注册服务对象
 	//s.RegisterName("Auth", new(handler.Auth), "")

+ 21 - 2
opms_parent/schema/contract.sql

@@ -98,7 +98,7 @@ CREATE TABLE `ctr_contract_invoice` (
     `invoice_amount` decimal(24, 6) NOT NULL COMMENT '开票金额',
     `invoice_date` datetime NOT NULL COMMENT '开票日期',
     `invoice_type` varchar(4) DEFAULT NULL COMMENT '开票类型',
-    `appro_status` varchar(4) DEFAULT NULL COMMENT '审核状态',
+    `appro_status` varchar(4) DEFAULT NULL COMMENT '审核状态 10 未通过 20 已通过',
     `invoice_code` varchar(32) DEFAULT NULL COMMENT '发票号码',
     `actual_invoice_date` datetime DEFAULT NULL COMMENT '实际开票日期',
     `courier_code` varchar(32) DEFAULT NULL COMMENT '快递单号',
@@ -133,7 +133,25 @@ CREATE TABLE `ctr_contract_product` (
     `updated_time` datetime DEFAULT NULL COMMENT '更新时间',
     `deleted_time` datetime DEFAULT NULL COMMENT '删除时间',
     PRIMARY KEY (`id`)
-) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '合同产品信息'
+) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '合同产品信息';
+CREATE TABLE `ctr_contract_dynamics` (
+    `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
+    `contract_id` int(11) NOT NULL COMMENT '合同ID',
+    `opn_people_id` int(11) NOT NULL COMMENT '操作人ID',
+    `opn_people` varchar(90) NOT NULL COMMENT '操作人',
+    `opn_date` datetime NOT NULL COMMENT '操作日期',
+    `opn_type` varchar(10) NOT NULL COMMENT '操作类型',
+    `opn_content` text DEFAULT NULL COMMENT '操作内容',
+    `remark` text DEFAULT NULL COMMENT '备注',
+    `created_by` int(11) NOT NULL COMMENT '创建者',
+    `created_name` varchar(90) NOT NULL COMMENT '创建人',
+    `created_time` datetime NOT NULL COMMENT '创建时间',
+    `updated_by` int(11) DEFAULT NULL COMMENT '更新者',
+    `updated_name` varchar(90) DEFAULT NULL COMMENT '更新人',
+    `updated_time` datetime DEFAULT NULL COMMENT '更新时间',
+    `deleted_time` datetime DEFAULT NULL COMMENT '删除时间',
+    PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='合同动态';
 
 
 -- ctr_contract                 合同信息
@@ -142,3 +160,4 @@ CREATE TABLE `ctr_contract_product` (
 -- ctr_contract_collection_plan 合同回款计划
 -- ctr_contract_invoice         合同发票信息
 -- ctr_contract_product         合同产品信息
+-- ctr_contract_dynamics        合同动态

+ 1 - 1
opms_parent/swaggerui/index.html

@@ -68,7 +68,7 @@
           let token = req.headers.Authorization
           if (!token) {
             // token = "Bearer ajg7o1Dts1JrKCm6VtgyuuaYbUIiirXxI5+6WzYnC7gWl+43NdKq6LbWxU1zWhsBaL0A/CIkBoefM0vuu6h4ZA=="
-            token = "Bearer XHPbgFL1HqGOuYvMihA4oPtWy0wLKFF3i20ah/rev5/3QeP7ztdVCmO3x0LljVl1"
+            token = "Bearer 5a9R22RiKGsqBigUbLyd6xpdKYbMJdTw9Aowx8cmbm2qH1V5W3xxR4gNAic8PuG/"
             // token = "Bearer EyQWHd05nop+PL71oABt/1i0zoXd7bym1bFMWMXorORLmyDuyowEDoiKq8DhP2lbZo9XTSMe31d0Q7RRnkDNLA=="
             // token = "Bearer 7XrzVhU+ibTV/77q7h0ETY+bEWy4r4g9wteUr/43vNadbuWG5y8wucSmeU0BRd/1"
           }

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1157 - 83
opms_parent/swaggerui/swagger.yml


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä