From 2def11ba83760b5be1361f10c3756cc0e9cfd165 Mon Sep 17 00:00:00 2001
From: zhangqian <zhangqian@123.com>
Date: 星期一, 14 八月 2023 09:32:13 +0800
Subject: [PATCH] merge

---
 service/salesDetails.go           |   30 
 model/salesReturnStatus.go        |    6 
 model/request/salesDetails.go     |   34 
 pkg/ecode/code.go                 |   14 
 constvar/serviceCollectionPlan.go |   12 
 constvar/salesRefund.go           |    7 
 docs/swagger.yaml                 |  237 ++++++
 api/v1/salesReturn.go             |   14 
 constvar/salesReturn.go           |    7 
 api/v1/salesRefund.go             |   33 
 constvar/receipt.go               |   13 
 constvar/saleRefund.go            |   15 
 model/request/salesReturn.go      |   25 
 model/serviceOrderStatus.go       |   14 
 service/salesReturn.go            |    2 
 model/interface.go                |    8 
 model/salesReturn.go              |   30 
 docs/docs.go                      |  339 ++++++++++
 service/invoice.go                |  145 ++++
 docs/swagger.json                 |  339 ++++++++++
 model/serviceCollectionPlan.go    |   61 +
 model/receipt.go                  |   28 
 model/model.go                    |   19 
 model/serviceContract.go          |   46 +
 model/salesDetails.go             |   71 ++
 model/salesRefund.go              |   89 ++
 service/salesRefund.go            |   45 +
 model/request/salesRefund.go      |   28 
 service/serviceContract.go        |   33 
 service/receipt.go                |  155 ++++
 pkg/ecode/msg.go                  |    2 
 31 files changed, 1,651 insertions(+), 250 deletions(-)

diff --git a/api/v1/salesRefund.go b/api/v1/salesRefund.go
index 8da5dd5..fcc02e1 100644
--- a/api/v1/salesRefund.go
+++ b/api/v1/salesRefund.go
@@ -98,34 +98,13 @@
 	ctx.Ok()
 }
 
-
 func checkSalesRefundParams(salesRefund request.SalesRefund) (errCode int, salesRefundRes model.SalesRefund) {
-	//if salesRefund.ClientId == 0 {
-	//	return ecode.InvalidParams, salesRefundRes
-	//}
-	//
-	//if salesRefund.Number == "" {
-	//	return ecode.InvalidParams, salesRefundRes
-	//}
-	//
-	//if salesRefund.MemberId == 0 {
-	//	return ecode.InvalidParams, salesRefundRes
-	//}
-	//
-	//if salesRefund.RefundDate == "" {
-	//	return ecode.InvalidParams, salesRefundRes
-	//}
-
-	t, err := checkTimeFormat(salesRefund.RefundDate)
-	if err != nil {
-		return ecode.InvalidParams, salesRefundRes
-	}
-	salesRefundRes.RefundDate = t
+	salesRefundRes.RefundDate = salesRefund.RefundDate
 	salesRefundRes.ClientId = salesRefund.ClientId
 	salesRefundRes.Number = salesRefund.Number
 	salesRefundRes.MemberId = salesRefund.MemberId
-	salesRefundRes.RefundMethod = salesRefund.RefundMethod
-	salesRefundRes.AccountId = salesRefund.AccountId
+	salesRefundRes.PaymentTypeId = salesRefund.PaymentTypeId
+	salesRefundRes.BankAccountId = salesRefund.BankAccountId
 	salesRefundRes.IsInvoice = salesRefund.IsInvoice
 	salesRefundRes.Reason = salesRefund.Reason
 	salesRefundRes.Products = salesRefund.Products
@@ -148,14 +127,14 @@
 		return
 	}
 
-	salesRefunds, total, errCode := salesRefundService.GetSalesRefundList(params.Page, params.PageSize, params.Keyword)
+	salesRefunds, total, errCode := salesRefundService.GetSalesRefundList(params.Page, params.PageSize, params.KeywordType, params.Keyword)
 	if errCode != ecode.OK {
 		ctx.Fail(errCode)
 		return
 	}
 
 	ctx.OkWithDetailed(response.SalesRefundResponse{
-		List: salesRefunds,
+		List:  salesRefunds,
 		Count: int(total),
 	})
-}
\ No newline at end of file
+}
diff --git a/api/v1/salesReturn.go b/api/v1/salesReturn.go
index 20b1949..e0c7990 100644
--- a/api/v1/salesReturn.go
+++ b/api/v1/salesReturn.go
@@ -99,7 +99,6 @@
 
 }
 
-
 func checkSalesReturnParams(salesReturn request.SalesReturn) (errCode int, s model.SalesReturn) {
 	//if salesReturn.Number == "" {
 	//	return ecode.InvalidParams, s
@@ -113,17 +112,12 @@
 	//	return ecode.InvalidParams, s
 	//}
 
-	t, err := checkTimeFormat(salesReturn.ReturnDate)
-	if err != nil {
-		return ecode.InvalidParams, s
-	}
-
 	s.ClientId = salesReturn.ClientId
-	s.ReturnDate = t
+	s.ReturnDate = salesReturn.ReturnDate
 	s.Number = salesReturn.Number
 	s.Repository = salesReturn.Repository
 	s.MemberId = salesReturn.MemberId
-	s.SalesReturnStatus = salesReturn.Status
+	s.SalesReturnStatusId = salesReturn.SalesReturnStatusId
 	s.Reason = salesReturn.Reason
 	s.Products = salesReturn.Products
 
@@ -152,7 +146,7 @@
 	}
 
 	ctx.OkWithDetailed(response.SalesReturnResponse{
-		List: salesReturns,
+		List:  salesReturns,
 		Count: int(total),
 	})
-}
\ No newline at end of file
+}
diff --git a/constvar/receipt.go b/constvar/receipt.go
index df8e86e..d0d04a8 100644
--- a/constvar/receipt.go
+++ b/constvar/receipt.go
@@ -1,4 +1,5 @@
 package constvar
+
 type ReceiptQueryClass string
 
 const (
@@ -8,5 +9,15 @@
 type ReceiptKeywordType string
 
 const (
-	ReceiptKeywordCustomerName   ReceiptKeywordType = ""
+	ReceiptKeywordCustomerName ReceiptKeywordType = ""
+)
+
+type ReceiptSourceType int //鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級
+
+const (
+	ReceiptSourceTypeSalesDetails    ReceiptSourceType = 1
+	ReceiptSourceTypeServiceContract ReceiptSourceType = 2
+	ReceiptSourceTypeInvoice         ReceiptSourceType = 3
+	ReceiptSourceTypeCollectionPlan  ReceiptSourceType = 4
+	ReceiptSourceTypeChuKuDan        ReceiptSourceType = 5
 )
diff --git a/constvar/saleRefund.go b/constvar/saleRefund.go
new file mode 100644
index 0000000..06d3f55
--- /dev/null
+++ b/constvar/saleRefund.go
@@ -0,0 +1,15 @@
+package constvar
+
+type SalesRefundKeywordType string
+
+const (
+	SalesRefundKeywordRefundNumber SalesRefundKeywordType = "閿�鍞��璐у崟缂栧彿"
+	SalesRefundKeywordClientName   SalesRefundKeywordType = "瀹㈡埛鍚嶇О"
+	SalesRefundKeywordRefundDate   SalesRefundKeywordType = "閫�娆炬棩鏈�"
+	SalesRefundKeywordAccount      SalesRefundKeywordType = "璐︽埛"
+	SalesRefundKeywordIsInvoice    SalesRefundKeywordType = "鏄惁寮�绁�"
+	SalesRefundKeywordPaymentType  SalesRefundKeywordType = "浠樻鏂瑰紡"
+	SalesRefundKeywordPrincipal    SalesRefundKeywordType = "閿�鍞礋璐d汉"
+	SalesRefundKeywordUpdateAt     SalesRefundKeywordType = "淇敼鏃堕棿"
+	SalesRefundKeywordPriceTotal   SalesRefundKeywordType = "浠风◣鍚堣"
+)
diff --git a/constvar/salesRefund.go b/constvar/salesRefund.go
new file mode 100644
index 0000000..0f65a91
--- /dev/null
+++ b/constvar/salesRefund.go
@@ -0,0 +1,7 @@
+package constvar
+
+type RefundSourceType int //鏉ユ簮绫诲瀷锛�1閿�鍞��璐э級
+
+const (
+	RefundSourceTypeSalesReturn RefundSourceType = 1 //閿�鍞��璐�
+)
diff --git a/constvar/salesReturn.go b/constvar/salesReturn.go
new file mode 100644
index 0000000..f86185f
--- /dev/null
+++ b/constvar/salesReturn.go
@@ -0,0 +1,7 @@
+package constvar
+
+type SalesReturnSourceType int
+
+const (
+	SalesReturnSourceTypeSaleDetails SalesReturnSourceType = 1 //閿�鍞槑缁�
+)
diff --git a/constvar/serviceCollectionPlan.go b/constvar/serviceCollectionPlan.go
index 6f32e72..c59acc5 100644
--- a/constvar/serviceCollectionPlan.go
+++ b/constvar/serviceCollectionPlan.go
@@ -15,6 +15,14 @@
 type CollectionStatus int
 
 const (
-	CollectionStatusUnCollected CollectionStatus = 1 //寰呮敹娆�
-	CollectionStatusCollected   CollectionStatus = 2 //宸叉敹娆�
+	CollectionStatusUnCollected  CollectionStatus = 1 //寰呮敹娆�
+	CollectionStatusSubCollected CollectionStatus = 2 //閮ㄥ垎鏀舵
+	CollectionStatusCollected    CollectionStatus = 3 //宸叉敹娆�
+)
+
+type CollectionSourceType int
+
+const (
+	CollectionSourceTypeSaleDetails     CollectionSourceType = 1 //閿�鍞槑缁�
+	CollectionSourceTypeServiceContract CollectionSourceType = 2 //鏈嶅姟鍚堝悓
 )
diff --git a/docs/docs.go b/docs/docs.go
index 414e949..6ac3333 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -9992,18 +9992,36 @@
                 "BankAccountQueryClassExpireLessThen60Days"
             ]
         },
-        "constvar.CollectionStatus": {
+        "constvar.CollectionSourceType": {
             "type": "integer",
             "enum": [
                 1,
                 2
             ],
             "x-enum-comments": {
+                "CollectionSourceTypeSaleDetails": "閿�鍞槑缁�",
+                "CollectionSourceTypeServiceContract": "鏈嶅姟鍚堝悓"
+            },
+            "x-enum-varnames": [
+                "CollectionSourceTypeSaleDetails",
+                "CollectionSourceTypeServiceContract"
+            ]
+        },
+        "constvar.CollectionStatus": {
+            "type": "integer",
+            "enum": [
+                1,
+                2,
+                3
+            ],
+            "x-enum-comments": {
                 "CollectionStatusCollected": "宸叉敹娆�",
+                "CollectionStatusSubCollected": "閮ㄥ垎鏀舵",
                 "CollectionStatusUnCollected": "寰呮敹娆�"
             },
             "x-enum-varnames": [
                 "CollectionStatusUnCollected",
+                "CollectionStatusSubCollected",
                 "CollectionStatusCollected"
             ]
         },
@@ -10144,6 +10162,35 @@
                 "ReceiptQueryClassExpireLessThen60Days"
             ]
         },
+        "constvar.ReceiptSourceType": {
+            "type": "integer",
+            "enum": [
+                1,
+                2,
+                3,
+                4,
+                5
+            ],
+            "x-enum-varnames": [
+                "ReceiptSourceTypeSalesDetails",
+                "ReceiptSourceTypeServiceContract",
+                "ReceiptSourceTypeInvoice",
+                "ReceiptSourceTypeCollectionPlan",
+                "ReceiptSourceTypeChuKuDan"
+            ]
+        },
+        "constvar.RefundSourceType": {
+            "type": "integer",
+            "enum": [
+                1
+            ],
+            "x-enum-comments": {
+                "RefundSourceTypeSalesReturn": "閿�鍞��璐�"
+            },
+            "x-enum-varnames": [
+                "RefundSourceTypeSalesReturn"
+            ]
+        },
         "constvar.SalesDetailsKeywordType": {
             "type": "string",
             "enum": [
@@ -10159,6 +10206,43 @@
                 "SalesDetailsKeywordTypeSignTime",
                 "SalesDetailsKeywordTypePrincipal",
                 "SalesDetailsKeywordTypeProductName"
+            ]
+        },
+        "constvar.SalesRefundKeywordType": {
+            "type": "string",
+            "enum": [
+                "閿�鍞��璐у崟缂栧彿",
+                "瀹㈡埛鍚嶇О",
+                "閫�娆炬棩鏈�",
+                "璐︽埛",
+                "鏄惁寮�绁�",
+                "浠樻鏂瑰紡",
+                "閿�鍞礋璐d汉",
+                "淇敼鏃堕棿",
+                "浠风◣鍚堣"
+            ],
+            "x-enum-varnames": [
+                "SalesRefundKeywordRefundNumber",
+                "SalesRefundKeywordClientName",
+                "SalesRefundKeywordRefundDate",
+                "SalesRefundKeywordAccount",
+                "SalesRefundKeywordIsInvoice",
+                "SalesRefundKeywordPaymentType",
+                "SalesRefundKeywordPrincipal",
+                "SalesRefundKeywordUpdateAt",
+                "SalesRefundKeywordPriceTotal"
+            ]
+        },
+        "constvar.SalesReturnSourceType": {
+            "type": "integer",
+            "enum": [
+                1
+            ],
+            "x-enum-comments": {
+                "SalesReturnSourceTypeSaleDetails": "閿�鍞槑缁�"
+            },
+            "x-enum-varnames": [
+                "SalesReturnSourceTypeSaleDetails"
             ]
         },
         "constvar.SalesStatus": {
@@ -11398,6 +11482,13 @@
         "model.Receipt": {
             "type": "object",
             "properties": {
+                "amount": {
+                    "description": "鏀舵閲戦",
+                    "type": "number"
+                },
+                "bankAccount": {
+                    "$ref": "#/definitions/model.BankAccount"
+                },
                 "bankAccountId": {
                     "description": "璐︽埛id",
                     "type": "integer"
@@ -11417,9 +11508,20 @@
                     "description": "甯佺",
                     "type": "string"
                 },
+                "paymentType": {
+                    "$ref": "#/definitions/model.PaymentType"
+                },
                 "paymentTypeId": {
                     "description": "鏀舵鏂瑰紡ID",
                     "type": "integer"
+                },
+                "principal": {
+                    "description": "璐熻矗浜篿d",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/model.User"
+                        }
+                    ]
                 },
                 "principalId": {
                     "description": "璐熻矗浜篿d",
@@ -11439,7 +11541,11 @@
                 },
                 "sourceType": {
                     "description": "鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級",
-                    "type": "integer"
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.ReceiptSourceType"
+                        }
+                    ]
                 }
             }
         },
@@ -11668,6 +11774,9 @@
         "model.SalesDetails": {
             "type": "object",
             "properties": {
+                "Member": {
+                    "$ref": "#/definitions/model.User"
+                },
                 "address": {
                     "type": "string"
                 },
@@ -11686,6 +11795,10 @@
                     "description": "宸叉敹閲戦",
                     "type": "number"
                 },
+                "amountTotal": {
+                    "description": "浠风◣鍚堣",
+                    "type": "number"
+                },
                 "amountUnInvoiced": {
                     "description": "鏈紑绁ㄩ噾棰�",
                     "type": "number"
@@ -11697,6 +11810,15 @@
                     "type": "integer"
                 },
                 "conditions": {
+                    "type": "string"
+                },
+                "createTime": {
+                    "type": "string"
+                },
+                "creatorId": {
+                    "type": "integer"
+                },
+                "creatorName": {
                     "type": "string"
                 },
                 "deliveryDate": {
@@ -11823,11 +11945,28 @@
         "model.SalesRefund": {
             "type": "object",
             "properties": {
-                "accountId": {
+                "amountTotal": {
+                    "description": "浠风◣鍚堣",
+                    "type": "number"
+                },
+                "bankAccount": {
+                    "$ref": "#/definitions/model.BankAccount"
+                },
+                "bankAccountId": {
+                    "description": "璐︽埛id",
                     "type": "integer"
+                },
+                "client": {
+                    "$ref": "#/definitions/model.Client"
                 },
                 "clientId": {
                     "type": "integer"
+                },
+                "createTime": {
+                    "type": "string"
+                },
+                "creatorName": {
+                    "type": "string"
                 },
                 "id": {
                     "type": "integer"
@@ -11835,11 +11974,21 @@
                 "isInvoice": {
                     "type": "integer"
                 },
+                "member": {
+                    "$ref": "#/definitions/model.User"
+                },
                 "memberId": {
                     "type": "integer"
                 },
                 "number": {
                     "type": "string"
+                },
+                "paymentType": {
+                    "$ref": "#/definitions/model.PaymentType"
+                },
+                "paymentTypeId": {
+                    "description": "鏀舵鏂瑰紡ID",
+                    "type": "integer"
                 },
                 "products": {
                     "type": "array",
@@ -11853,16 +12002,45 @@
                 "refundDate": {
                     "type": "string"
                 },
-                "refundMethod": {
-                    "type": "string"
+                "sourceId": {
+                    "description": "婧愬崟id",
+                    "type": "integer"
+                },
+                "sourceType": {
+                    "description": "鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.RefundSourceType"
+                        }
+                    ]
                 }
             }
         },
         "model.SalesReturn": {
             "type": "object",
             "properties": {
+                "Member": {
+                    "$ref": "#/definitions/model.User"
+                },
+                "SalesReturnStatus": {
+                    "description": "閫�璐х姸鎬�",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/model.SalesReturnStatus"
+                        }
+                    ]
+                },
+                "client": {
+                    "$ref": "#/definitions/model.Client"
+                },
                 "clientId": {
                     "type": "integer"
+                },
+                "createTime": {
+                    "type": "string"
+                },
+                "creatorName": {
+                    "type": "string"
                 },
                 "id": {
                     "type": "integer"
@@ -11874,22 +12052,38 @@
                     "type": "string"
                 },
                 "products": {
+                    "description": "閫�璐т骇鍝�",
                     "type": "array",
                     "items": {
                         "$ref": "#/definitions/model.Product"
                     }
                 },
                 "reason": {
+                    "description": "閫�璐у師鍥�",
                     "type": "string"
                 },
                 "repository": {
                     "type": "string"
                 },
                 "returnDate": {
+                    "description": "閫�璐ф棩鏈�",
                     "type": "string"
                 },
-                "salesReturnStatus": {
+                "salesReturnStatusId": {
+                    "description": "閫�璐х姸鎬乮d",
                     "type": "integer"
+                },
+                "sourceId": {
+                    "description": "婧愬崟id",
+                    "type": "integer"
+                },
+                "sourceType": {
+                    "description": "婧愬崟绫诲瀷锛�1閿�鍞槑缁嗭級",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.SalesReturnSourceType"
+                        }
+                    ]
                 }
             }
         },
@@ -11933,6 +12127,18 @@
                     "description": "閲戦",
                     "type": "number"
                 },
+                "amountReceivable": {
+                    "description": "搴旀敹閲戦",
+                    "type": "number"
+                },
+                "amountReceived": {
+                    "description": "宸叉敹閲戦",
+                    "type": "number"
+                },
+                "amountTotal": {
+                    "description": "鎬婚",
+                    "type": "number"
+                },
                 "collectionDate": {
                     "description": "璁″垝鏀舵鏃ユ湡",
                     "type": "string"
@@ -11970,10 +12176,14 @@
                 },
                 "sourceType": {
                     "description": "婧愬崟绫诲瀷锛�1閿�鍞槑缁�2鏈嶅姟鍚堝悓3閿�鍞彂绁級",
-                    "type": "integer"
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.CollectionSourceType"
+                        }
+                    ]
                 },
                 "status": {
-                    "description": "鐘舵�侊紙1鏈敹2宸叉敹锛�",
+                    "description": "鐘舵�侊紙1鏈敹2閮ㄥ垎宸叉敹3宸叉敹锛�",
                     "allOf": [
                         {
                             "$ref": "#/definitions/constvar.CollectionStatus"
@@ -12002,6 +12212,10 @@
                 },
                 "amountReceived": {
                     "description": "宸叉敹閲戦",
+                    "type": "number"
+                },
+                "amountTotal": {
+                    "description": "浠风◣鍚堣",
                     "type": "number"
                 },
                 "amountUnInvoiced": {
@@ -13249,6 +13463,13 @@
         "request.AddReceipt": {
             "type": "object",
             "properties": {
+                "amount": {
+                    "description": "鏀舵閲戦",
+                    "type": "number"
+                },
+                "bankAccount": {
+                    "$ref": "#/definitions/model.BankAccount"
+                },
                 "bankAccountId": {
                     "description": "璐︽埛id",
                     "type": "integer"
@@ -13268,9 +13489,20 @@
                     "description": "甯佺",
                     "type": "string"
                 },
+                "paymentType": {
+                    "$ref": "#/definitions/model.PaymentType"
+                },
                 "paymentTypeId": {
                     "description": "鏀舵鏂瑰紡ID",
                     "type": "integer"
+                },
+                "principal": {
+                    "description": "璐熻矗浜篿d",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/model.User"
+                        }
+                    ]
                 },
                 "principalId": {
                     "description": "璐熻矗浜篿d",
@@ -13290,7 +13522,11 @@
                 },
                 "sourceType": {
                     "description": "鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級",
-                    "type": "integer"
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.ReceiptSourceType"
+                        }
+                    ]
                 }
             }
         },
@@ -14671,6 +14907,9 @@
                 "keyword": {
                     "type": "string"
                 },
+                "keywordType": {
+                    "$ref": "#/definitions/constvar.SalesRefundKeywordType"
+                },
                 "page": {
                     "description": "椤电爜",
                     "type": "integer"
@@ -15020,7 +15259,8 @@
         "request.SalesRefund": {
             "type": "object",
             "properties": {
-                "accountId": {
+                "bankAccountId": {
+                    "description": "璐︽埛id",
                     "type": "integer"
                 },
                 "clientId": {
@@ -15035,6 +15275,10 @@
                 "number": {
                     "type": "string"
                 },
+                "paymentTypeId": {
+                    "description": "鏀舵鏂瑰紡ID",
+                    "type": "integer"
+                },
                 "products": {
                     "type": "array",
                     "items": {
@@ -15047,8 +15291,17 @@
                 "refundDate": {
                     "type": "string"
                 },
-                "refundMethod": {
-                    "type": "string"
+                "sourceId": {
+                    "description": "婧愬崟id",
+                    "type": "integer"
+                },
+                "sourceType": {
+                    "description": "鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.RefundSourceType"
+                        }
+                    ]
                 }
             }
         },
@@ -15065,22 +15318,38 @@
                     "type": "string"
                 },
                 "products": {
+                    "description": "閫�璐т骇鍝�",
                     "type": "array",
                     "items": {
                         "$ref": "#/definitions/model.Product"
                     }
                 },
                 "reason": {
+                    "description": "閫�璐у師鍥�",
                     "type": "string"
                 },
                 "repository": {
                     "type": "string"
                 },
                 "returnDate": {
+                    "description": "閫�璐ф棩鏈�",
                     "type": "string"
                 },
-                "status": {
+                "salesReturnStatusId": {
+                    "description": "閫�璐х姸鎬乮d",
                     "type": "integer"
+                },
+                "sourceId": {
+                    "description": "婧愬崟id",
+                    "type": "integer"
+                },
+                "sourceType": {
+                    "description": "婧愬崟绫诲瀷锛�1閿�鍞槑缁嗭級",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.SalesReturnSourceType"
+                        }
+                    ]
                 }
             }
         },
@@ -16156,6 +16425,13 @@
         "request.UpdateReceipt": {
             "type": "object",
             "properties": {
+                "amount": {
+                    "description": "鏀舵閲戦",
+                    "type": "number"
+                },
+                "bankAccount": {
+                    "$ref": "#/definitions/model.BankAccount"
+                },
                 "bankAccountId": {
                     "description": "璐︽埛id",
                     "type": "integer"
@@ -16175,9 +16451,20 @@
                     "description": "甯佺",
                     "type": "string"
                 },
+                "paymentType": {
+                    "$ref": "#/definitions/model.PaymentType"
+                },
                 "paymentTypeId": {
                     "description": "鏀舵鏂瑰紡ID",
                     "type": "integer"
+                },
+                "principal": {
+                    "description": "璐熻矗浜篿d",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/model.User"
+                        }
+                    ]
                 },
                 "principalId": {
                     "description": "璐熻矗浜篿d",
@@ -16197,7 +16484,11 @@
                 },
                 "sourceType": {
                     "description": "鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級",
-                    "type": "integer"
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.ReceiptSourceType"
+                        }
+                    ]
                 }
             }
         },
@@ -16712,6 +17003,18 @@
                     "description": "閲戦",
                     "type": "number"
                 },
+                "amountReceivable": {
+                    "description": "搴旀敹閲戦",
+                    "type": "number"
+                },
+                "amountReceived": {
+                    "description": "宸叉敹閲戦",
+                    "type": "number"
+                },
+                "amountTotal": {
+                    "description": "鎬婚",
+                    "type": "number"
+                },
                 "collectionDate": {
                     "description": "璁″垝鏀舵鏃ユ湡",
                     "type": "string"
@@ -16749,10 +17052,14 @@
                 },
                 "sourceType": {
                     "description": "婧愬崟绫诲瀷锛�1閿�鍞槑缁�2鏈嶅姟鍚堝悓3閿�鍞彂绁級",
-                    "type": "integer"
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.CollectionSourceType"
+                        }
+                    ]
                 },
                 "status": {
-                    "description": "鐘舵�侊紙1鏈敹2宸叉敹锛�",
+                    "description": "鐘舵�侊紙1鏈敹2閮ㄥ垎宸叉敹3宸叉敹锛�",
                     "allOf": [
                         {
                             "$ref": "#/definitions/constvar.CollectionStatus"
diff --git a/docs/swagger.json b/docs/swagger.json
index 26776dd..d2b7a58 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -9980,18 +9980,36 @@
                 "BankAccountQueryClassExpireLessThen60Days"
             ]
         },
-        "constvar.CollectionStatus": {
+        "constvar.CollectionSourceType": {
             "type": "integer",
             "enum": [
                 1,
                 2
             ],
             "x-enum-comments": {
+                "CollectionSourceTypeSaleDetails": "閿�鍞槑缁�",
+                "CollectionSourceTypeServiceContract": "鏈嶅姟鍚堝悓"
+            },
+            "x-enum-varnames": [
+                "CollectionSourceTypeSaleDetails",
+                "CollectionSourceTypeServiceContract"
+            ]
+        },
+        "constvar.CollectionStatus": {
+            "type": "integer",
+            "enum": [
+                1,
+                2,
+                3
+            ],
+            "x-enum-comments": {
                 "CollectionStatusCollected": "宸叉敹娆�",
+                "CollectionStatusSubCollected": "閮ㄥ垎鏀舵",
                 "CollectionStatusUnCollected": "寰呮敹娆�"
             },
             "x-enum-varnames": [
                 "CollectionStatusUnCollected",
+                "CollectionStatusSubCollected",
                 "CollectionStatusCollected"
             ]
         },
@@ -10132,6 +10150,35 @@
                 "ReceiptQueryClassExpireLessThen60Days"
             ]
         },
+        "constvar.ReceiptSourceType": {
+            "type": "integer",
+            "enum": [
+                1,
+                2,
+                3,
+                4,
+                5
+            ],
+            "x-enum-varnames": [
+                "ReceiptSourceTypeSalesDetails",
+                "ReceiptSourceTypeServiceContract",
+                "ReceiptSourceTypeInvoice",
+                "ReceiptSourceTypeCollectionPlan",
+                "ReceiptSourceTypeChuKuDan"
+            ]
+        },
+        "constvar.RefundSourceType": {
+            "type": "integer",
+            "enum": [
+                1
+            ],
+            "x-enum-comments": {
+                "RefundSourceTypeSalesReturn": "閿�鍞��璐�"
+            },
+            "x-enum-varnames": [
+                "RefundSourceTypeSalesReturn"
+            ]
+        },
         "constvar.SalesDetailsKeywordType": {
             "type": "string",
             "enum": [
@@ -10147,6 +10194,43 @@
                 "SalesDetailsKeywordTypeSignTime",
                 "SalesDetailsKeywordTypePrincipal",
                 "SalesDetailsKeywordTypeProductName"
+            ]
+        },
+        "constvar.SalesRefundKeywordType": {
+            "type": "string",
+            "enum": [
+                "閿�鍞��璐у崟缂栧彿",
+                "瀹㈡埛鍚嶇О",
+                "閫�娆炬棩鏈�",
+                "璐︽埛",
+                "鏄惁寮�绁�",
+                "浠樻鏂瑰紡",
+                "閿�鍞礋璐d汉",
+                "淇敼鏃堕棿",
+                "浠风◣鍚堣"
+            ],
+            "x-enum-varnames": [
+                "SalesRefundKeywordRefundNumber",
+                "SalesRefundKeywordClientName",
+                "SalesRefundKeywordRefundDate",
+                "SalesRefundKeywordAccount",
+                "SalesRefundKeywordIsInvoice",
+                "SalesRefundKeywordPaymentType",
+                "SalesRefundKeywordPrincipal",
+                "SalesRefundKeywordUpdateAt",
+                "SalesRefundKeywordPriceTotal"
+            ]
+        },
+        "constvar.SalesReturnSourceType": {
+            "type": "integer",
+            "enum": [
+                1
+            ],
+            "x-enum-comments": {
+                "SalesReturnSourceTypeSaleDetails": "閿�鍞槑缁�"
+            },
+            "x-enum-varnames": [
+                "SalesReturnSourceTypeSaleDetails"
             ]
         },
         "constvar.SalesStatus": {
@@ -11386,6 +11470,13 @@
         "model.Receipt": {
             "type": "object",
             "properties": {
+                "amount": {
+                    "description": "鏀舵閲戦",
+                    "type": "number"
+                },
+                "bankAccount": {
+                    "$ref": "#/definitions/model.BankAccount"
+                },
                 "bankAccountId": {
                     "description": "璐︽埛id",
                     "type": "integer"
@@ -11405,9 +11496,20 @@
                     "description": "甯佺",
                     "type": "string"
                 },
+                "paymentType": {
+                    "$ref": "#/definitions/model.PaymentType"
+                },
                 "paymentTypeId": {
                     "description": "鏀舵鏂瑰紡ID",
                     "type": "integer"
+                },
+                "principal": {
+                    "description": "璐熻矗浜篿d",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/model.User"
+                        }
+                    ]
                 },
                 "principalId": {
                     "description": "璐熻矗浜篿d",
@@ -11427,7 +11529,11 @@
                 },
                 "sourceType": {
                     "description": "鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級",
-                    "type": "integer"
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.ReceiptSourceType"
+                        }
+                    ]
                 }
             }
         },
@@ -11656,6 +11762,9 @@
         "model.SalesDetails": {
             "type": "object",
             "properties": {
+                "Member": {
+                    "$ref": "#/definitions/model.User"
+                },
                 "address": {
                     "type": "string"
                 },
@@ -11674,6 +11783,10 @@
                     "description": "宸叉敹閲戦",
                     "type": "number"
                 },
+                "amountTotal": {
+                    "description": "浠风◣鍚堣",
+                    "type": "number"
+                },
                 "amountUnInvoiced": {
                     "description": "鏈紑绁ㄩ噾棰�",
                     "type": "number"
@@ -11685,6 +11798,15 @@
                     "type": "integer"
                 },
                 "conditions": {
+                    "type": "string"
+                },
+                "createTime": {
+                    "type": "string"
+                },
+                "creatorId": {
+                    "type": "integer"
+                },
+                "creatorName": {
                     "type": "string"
                 },
                 "deliveryDate": {
@@ -11811,11 +11933,28 @@
         "model.SalesRefund": {
             "type": "object",
             "properties": {
-                "accountId": {
+                "amountTotal": {
+                    "description": "浠风◣鍚堣",
+                    "type": "number"
+                },
+                "bankAccount": {
+                    "$ref": "#/definitions/model.BankAccount"
+                },
+                "bankAccountId": {
+                    "description": "璐︽埛id",
                     "type": "integer"
+                },
+                "client": {
+                    "$ref": "#/definitions/model.Client"
                 },
                 "clientId": {
                     "type": "integer"
+                },
+                "createTime": {
+                    "type": "string"
+                },
+                "creatorName": {
+                    "type": "string"
                 },
                 "id": {
                     "type": "integer"
@@ -11823,11 +11962,21 @@
                 "isInvoice": {
                     "type": "integer"
                 },
+                "member": {
+                    "$ref": "#/definitions/model.User"
+                },
                 "memberId": {
                     "type": "integer"
                 },
                 "number": {
                     "type": "string"
+                },
+                "paymentType": {
+                    "$ref": "#/definitions/model.PaymentType"
+                },
+                "paymentTypeId": {
+                    "description": "鏀舵鏂瑰紡ID",
+                    "type": "integer"
                 },
                 "products": {
                     "type": "array",
@@ -11841,16 +11990,45 @@
                 "refundDate": {
                     "type": "string"
                 },
-                "refundMethod": {
-                    "type": "string"
+                "sourceId": {
+                    "description": "婧愬崟id",
+                    "type": "integer"
+                },
+                "sourceType": {
+                    "description": "鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.RefundSourceType"
+                        }
+                    ]
                 }
             }
         },
         "model.SalesReturn": {
             "type": "object",
             "properties": {
+                "Member": {
+                    "$ref": "#/definitions/model.User"
+                },
+                "SalesReturnStatus": {
+                    "description": "閫�璐х姸鎬�",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/model.SalesReturnStatus"
+                        }
+                    ]
+                },
+                "client": {
+                    "$ref": "#/definitions/model.Client"
+                },
                 "clientId": {
                     "type": "integer"
+                },
+                "createTime": {
+                    "type": "string"
+                },
+                "creatorName": {
+                    "type": "string"
                 },
                 "id": {
                     "type": "integer"
@@ -11862,22 +12040,38 @@
                     "type": "string"
                 },
                 "products": {
+                    "description": "閫�璐т骇鍝�",
                     "type": "array",
                     "items": {
                         "$ref": "#/definitions/model.Product"
                     }
                 },
                 "reason": {
+                    "description": "閫�璐у師鍥�",
                     "type": "string"
                 },
                 "repository": {
                     "type": "string"
                 },
                 "returnDate": {
+                    "description": "閫�璐ф棩鏈�",
                     "type": "string"
                 },
-                "salesReturnStatus": {
+                "salesReturnStatusId": {
+                    "description": "閫�璐х姸鎬乮d",
                     "type": "integer"
+                },
+                "sourceId": {
+                    "description": "婧愬崟id",
+                    "type": "integer"
+                },
+                "sourceType": {
+                    "description": "婧愬崟绫诲瀷锛�1閿�鍞槑缁嗭級",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.SalesReturnSourceType"
+                        }
+                    ]
                 }
             }
         },
@@ -11921,6 +12115,18 @@
                     "description": "閲戦",
                     "type": "number"
                 },
+                "amountReceivable": {
+                    "description": "搴旀敹閲戦",
+                    "type": "number"
+                },
+                "amountReceived": {
+                    "description": "宸叉敹閲戦",
+                    "type": "number"
+                },
+                "amountTotal": {
+                    "description": "鎬婚",
+                    "type": "number"
+                },
                 "collectionDate": {
                     "description": "璁″垝鏀舵鏃ユ湡",
                     "type": "string"
@@ -11958,10 +12164,14 @@
                 },
                 "sourceType": {
                     "description": "婧愬崟绫诲瀷锛�1閿�鍞槑缁�2鏈嶅姟鍚堝悓3閿�鍞彂绁級",
-                    "type": "integer"
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.CollectionSourceType"
+                        }
+                    ]
                 },
                 "status": {
-                    "description": "鐘舵�侊紙1鏈敹2宸叉敹锛�",
+                    "description": "鐘舵�侊紙1鏈敹2閮ㄥ垎宸叉敹3宸叉敹锛�",
                     "allOf": [
                         {
                             "$ref": "#/definitions/constvar.CollectionStatus"
@@ -11990,6 +12200,10 @@
                 },
                 "amountReceived": {
                     "description": "宸叉敹閲戦",
+                    "type": "number"
+                },
+                "amountTotal": {
+                    "description": "浠风◣鍚堣",
                     "type": "number"
                 },
                 "amountUnInvoiced": {
@@ -13237,6 +13451,13 @@
         "request.AddReceipt": {
             "type": "object",
             "properties": {
+                "amount": {
+                    "description": "鏀舵閲戦",
+                    "type": "number"
+                },
+                "bankAccount": {
+                    "$ref": "#/definitions/model.BankAccount"
+                },
                 "bankAccountId": {
                     "description": "璐︽埛id",
                     "type": "integer"
@@ -13256,9 +13477,20 @@
                     "description": "甯佺",
                     "type": "string"
                 },
+                "paymentType": {
+                    "$ref": "#/definitions/model.PaymentType"
+                },
                 "paymentTypeId": {
                     "description": "鏀舵鏂瑰紡ID",
                     "type": "integer"
+                },
+                "principal": {
+                    "description": "璐熻矗浜篿d",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/model.User"
+                        }
+                    ]
                 },
                 "principalId": {
                     "description": "璐熻矗浜篿d",
@@ -13278,7 +13510,11 @@
                 },
                 "sourceType": {
                     "description": "鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級",
-                    "type": "integer"
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.ReceiptSourceType"
+                        }
+                    ]
                 }
             }
         },
@@ -14659,6 +14895,9 @@
                 "keyword": {
                     "type": "string"
                 },
+                "keywordType": {
+                    "$ref": "#/definitions/constvar.SalesRefundKeywordType"
+                },
                 "page": {
                     "description": "椤电爜",
                     "type": "integer"
@@ -15008,7 +15247,8 @@
         "request.SalesRefund": {
             "type": "object",
             "properties": {
-                "accountId": {
+                "bankAccountId": {
+                    "description": "璐︽埛id",
                     "type": "integer"
                 },
                 "clientId": {
@@ -15023,6 +15263,10 @@
                 "number": {
                     "type": "string"
                 },
+                "paymentTypeId": {
+                    "description": "鏀舵鏂瑰紡ID",
+                    "type": "integer"
+                },
                 "products": {
                     "type": "array",
                     "items": {
@@ -15035,8 +15279,17 @@
                 "refundDate": {
                     "type": "string"
                 },
-                "refundMethod": {
-                    "type": "string"
+                "sourceId": {
+                    "description": "婧愬崟id",
+                    "type": "integer"
+                },
+                "sourceType": {
+                    "description": "鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.RefundSourceType"
+                        }
+                    ]
                 }
             }
         },
@@ -15053,22 +15306,38 @@
                     "type": "string"
                 },
                 "products": {
+                    "description": "閫�璐т骇鍝�",
                     "type": "array",
                     "items": {
                         "$ref": "#/definitions/model.Product"
                     }
                 },
                 "reason": {
+                    "description": "閫�璐у師鍥�",
                     "type": "string"
                 },
                 "repository": {
                     "type": "string"
                 },
                 "returnDate": {
+                    "description": "閫�璐ф棩鏈�",
                     "type": "string"
                 },
-                "status": {
+                "salesReturnStatusId": {
+                    "description": "閫�璐х姸鎬乮d",
                     "type": "integer"
+                },
+                "sourceId": {
+                    "description": "婧愬崟id",
+                    "type": "integer"
+                },
+                "sourceType": {
+                    "description": "婧愬崟绫诲瀷锛�1閿�鍞槑缁嗭級",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.SalesReturnSourceType"
+                        }
+                    ]
                 }
             }
         },
@@ -16144,6 +16413,13 @@
         "request.UpdateReceipt": {
             "type": "object",
             "properties": {
+                "amount": {
+                    "description": "鏀舵閲戦",
+                    "type": "number"
+                },
+                "bankAccount": {
+                    "$ref": "#/definitions/model.BankAccount"
+                },
                 "bankAccountId": {
                     "description": "璐︽埛id",
                     "type": "integer"
@@ -16163,9 +16439,20 @@
                     "description": "甯佺",
                     "type": "string"
                 },
+                "paymentType": {
+                    "$ref": "#/definitions/model.PaymentType"
+                },
                 "paymentTypeId": {
                     "description": "鏀舵鏂瑰紡ID",
                     "type": "integer"
+                },
+                "principal": {
+                    "description": "璐熻矗浜篿d",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/model.User"
+                        }
+                    ]
                 },
                 "principalId": {
                     "description": "璐熻矗浜篿d",
@@ -16185,7 +16472,11 @@
                 },
                 "sourceType": {
                     "description": "鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級",
-                    "type": "integer"
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.ReceiptSourceType"
+                        }
+                    ]
                 }
             }
         },
@@ -16700,6 +16991,18 @@
                     "description": "閲戦",
                     "type": "number"
                 },
+                "amountReceivable": {
+                    "description": "搴旀敹閲戦",
+                    "type": "number"
+                },
+                "amountReceived": {
+                    "description": "宸叉敹閲戦",
+                    "type": "number"
+                },
+                "amountTotal": {
+                    "description": "鎬婚",
+                    "type": "number"
+                },
                 "collectionDate": {
                     "description": "璁″垝鏀舵鏃ユ湡",
                     "type": "string"
@@ -16737,10 +17040,14 @@
                 },
                 "sourceType": {
                     "description": "婧愬崟绫诲瀷锛�1閿�鍞槑缁�2鏈嶅姟鍚堝悓3閿�鍞彂绁級",
-                    "type": "integer"
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/constvar.CollectionSourceType"
+                        }
+                    ]
                 },
                 "status": {
-                    "description": "鐘舵�侊紙1鏈敹2宸叉敹锛�",
+                    "description": "鐘舵�侊紙1鏈敹2閮ㄥ垎宸叉敹3宸叉敹锛�",
                     "allOf": [
                         {
                             "$ref": "#/definitions/constvar.CollectionStatus"
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index 65383ab..4ab2384 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -11,16 +11,30 @@
     type: string
     x-enum-varnames:
     - BankAccountQueryClassExpireLessThen60Days
-  constvar.CollectionStatus:
+  constvar.CollectionSourceType:
     enum:
     - 1
     - 2
     type: integer
     x-enum-comments:
+      CollectionSourceTypeSaleDetails: 閿�鍞槑缁�
+      CollectionSourceTypeServiceContract: 鏈嶅姟鍚堝悓
+    x-enum-varnames:
+    - CollectionSourceTypeSaleDetails
+    - CollectionSourceTypeServiceContract
+  constvar.CollectionStatus:
+    enum:
+    - 1
+    - 2
+    - 3
+    type: integer
+    x-enum-comments:
       CollectionStatusCollected: 宸叉敹娆�
+      CollectionStatusSubCollected: 閮ㄥ垎鏀舵
       CollectionStatusUnCollected: 寰呮敹娆�
     x-enum-varnames:
     - CollectionStatusUnCollected
+    - CollectionStatusSubCollected
     - CollectionStatusCollected
   constvar.CourierCompanyKeywordType:
     enum:
@@ -114,6 +128,28 @@
     type: string
     x-enum-varnames:
     - ReceiptQueryClassExpireLessThen60Days
+  constvar.ReceiptSourceType:
+    enum:
+    - 1
+    - 2
+    - 3
+    - 4
+    - 5
+    type: integer
+    x-enum-varnames:
+    - ReceiptSourceTypeSalesDetails
+    - ReceiptSourceTypeServiceContract
+    - ReceiptSourceTypeInvoice
+    - ReceiptSourceTypeCollectionPlan
+    - ReceiptSourceTypeChuKuDan
+  constvar.RefundSourceType:
+    enum:
+    - 1
+    type: integer
+    x-enum-comments:
+      RefundSourceTypeSalesReturn: 閿�鍞��璐�
+    x-enum-varnames:
+    - RefundSourceTypeSalesReturn
   constvar.SalesDetailsKeywordType:
     enum:
     - 瀹㈡埛鍚嶇О
@@ -128,6 +164,36 @@
     - SalesDetailsKeywordTypeSignTime
     - SalesDetailsKeywordTypePrincipal
     - SalesDetailsKeywordTypeProductName
+  constvar.SalesRefundKeywordType:
+    enum:
+    - 閿�鍞��璐у崟缂栧彿
+    - 瀹㈡埛鍚嶇О
+    - 閫�娆炬棩鏈�
+    - 璐︽埛
+    - 鏄惁寮�绁�
+    - 浠樻鏂瑰紡
+    - 閿�鍞礋璐d汉
+    - 淇敼鏃堕棿
+    - 浠风◣鍚堣
+    type: string
+    x-enum-varnames:
+    - SalesRefundKeywordRefundNumber
+    - SalesRefundKeywordClientName
+    - SalesRefundKeywordRefundDate
+    - SalesRefundKeywordAccount
+    - SalesRefundKeywordIsInvoice
+    - SalesRefundKeywordPaymentType
+    - SalesRefundKeywordPrincipal
+    - SalesRefundKeywordUpdateAt
+    - SalesRefundKeywordPriceTotal
+  constvar.SalesReturnSourceType:
+    enum:
+    - 1
+    type: integer
+    x-enum-comments:
+      SalesReturnSourceTypeSaleDetails: 閿�鍞槑缁�
+    x-enum-varnames:
+    - SalesReturnSourceTypeSaleDetails
   constvar.SalesStatus:
     enum:
     - 0
@@ -983,6 +1049,11 @@
     type: object
   model.Receipt:
     properties:
+      amount:
+        description: 鏀舵閲戦
+        type: number
+      bankAccount:
+        $ref: '#/definitions/model.BankAccount'
       bankAccountId:
         description: 璐︽埛id
         type: integer
@@ -997,9 +1068,15 @@
       moneyType:
         description: 甯佺
         type: string
+      paymentType:
+        $ref: '#/definitions/model.PaymentType'
       paymentTypeId:
         description: 鏀舵鏂瑰紡ID
         type: integer
+      principal:
+        allOf:
+        - $ref: '#/definitions/model.User'
+        description: 璐熻矗浜篿d
       principalId:
         description: 璐熻矗浜篿d
         type: integer
@@ -1013,8 +1090,9 @@
         description: 婧愬崟id
         type: integer
       sourceType:
+        allOf:
+        - $ref: '#/definitions/constvar.ReceiptSourceType'
         description: 鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級
-        type: integer
     type: object
   model.RefundMethod:
     properties:
@@ -1163,6 +1241,8 @@
     type: object
   model.SalesDetails:
     properties:
+      Member:
+        $ref: '#/definitions/model.User'
       address:
         type: string
       addressee:
@@ -1176,6 +1256,9 @@
       amountReceived:
         description: 宸叉敹閲戦
         type: number
+      amountTotal:
+        description: 浠风◣鍚堣
+        type: number
       amountUnInvoiced:
         description: 鏈紑绁ㄩ噾棰�
         type: number
@@ -1184,6 +1267,12 @@
       clientId:
         type: integer
       conditions:
+        type: string
+      createTime:
+        type: string
+      creatorId:
+        type: integer
+      creatorName:
         type: string
       deliveryDate:
         type: string
@@ -1267,18 +1356,37 @@
     type: object
   model.SalesRefund:
     properties:
-      accountId:
+      amountTotal:
+        description: 浠风◣鍚堣
+        type: number
+      bankAccount:
+        $ref: '#/definitions/model.BankAccount'
+      bankAccountId:
+        description: 璐︽埛id
         type: integer
+      client:
+        $ref: '#/definitions/model.Client'
       clientId:
         type: integer
+      createTime:
+        type: string
+      creatorName:
+        type: string
       id:
         type: integer
       isInvoice:
         type: integer
+      member:
+        $ref: '#/definitions/model.User'
       memberId:
         type: integer
       number:
         type: string
+      paymentType:
+        $ref: '#/definitions/model.PaymentType'
+      paymentTypeId:
+        description: 鏀舵鏂瑰紡ID
+        type: integer
       products:
         items:
           $ref: '#/definitions/model.Product'
@@ -1287,13 +1395,30 @@
         type: string
       refundDate:
         type: string
-      refundMethod:
-        type: string
+      sourceId:
+        description: 婧愬崟id
+        type: integer
+      sourceType:
+        allOf:
+        - $ref: '#/definitions/constvar.RefundSourceType'
+        description: 鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級
     type: object
   model.SalesReturn:
     properties:
+      Member:
+        $ref: '#/definitions/model.User'
+      SalesReturnStatus:
+        allOf:
+        - $ref: '#/definitions/model.SalesReturnStatus'
+        description: 閫�璐х姸鎬�
+      client:
+        $ref: '#/definitions/model.Client'
       clientId:
         type: integer
+      createTime:
+        type: string
+      creatorName:
+        type: string
       id:
         type: integer
       memberId:
@@ -1301,17 +1426,28 @@
       number:
         type: string
       products:
+        description: 閫�璐т骇鍝�
         items:
           $ref: '#/definitions/model.Product'
         type: array
       reason:
+        description: 閫�璐у師鍥�
         type: string
       repository:
         type: string
       returnDate:
+        description: 閫�璐ф棩鏈�
         type: string
-      salesReturnStatus:
+      salesReturnStatusId:
+        description: 閫�璐х姸鎬乮d
         type: integer
+      sourceId:
+        description: 婧愬崟id
+        type: integer
+      sourceType:
+        allOf:
+        - $ref: '#/definitions/constvar.SalesReturnSourceType'
+        description: 婧愬崟绫诲瀷锛�1閿�鍞槑缁嗭級
     type: object
   model.SalesReturnStatus:
     properties:
@@ -1338,6 +1474,15 @@
     properties:
       amount:
         description: 閲戦
+        type: number
+      amountReceivable:
+        description: 搴旀敹閲戦
+        type: number
+      amountReceived:
+        description: 宸叉敹閲戦
+        type: number
+      amountTotal:
+        description: 鎬婚
         type: number
       collectionDate:
         description: 璁″垝鏀舵鏃ユ湡
@@ -1366,12 +1511,13 @@
         description: 婧愬崟id
         type: integer
       sourceType:
+        allOf:
+        - $ref: '#/definitions/constvar.CollectionSourceType'
         description: 婧愬崟绫诲瀷锛�1閿�鍞槑缁�2鏈嶅姟鍚堝悓3閿�鍞彂绁級
-        type: integer
       status:
         allOf:
         - $ref: '#/definitions/constvar.CollectionStatus'
-        description: 鐘舵�侊紙1鏈敹2宸叉敹锛�
+        description: 鐘舵�侊紙1鏈敹2閮ㄥ垎宸叉敹3宸叉敹锛�
       term:
         description: 鏈熸
         type: integer
@@ -1388,6 +1534,9 @@
         type: number
       amountReceived:
         description: 宸叉敹閲戦
+        type: number
+      amountTotal:
+        description: 浠风◣鍚堣
         type: number
       amountUnInvoiced:
         description: 鏈紑绁ㄩ噾棰�
@@ -2231,6 +2380,11 @@
     type: object
   request.AddReceipt:
     properties:
+      amount:
+        description: 鏀舵閲戦
+        type: number
+      bankAccount:
+        $ref: '#/definitions/model.BankAccount'
       bankAccountId:
         description: 璐︽埛id
         type: integer
@@ -2245,9 +2399,15 @@
       moneyType:
         description: 甯佺
         type: string
+      paymentType:
+        $ref: '#/definitions/model.PaymentType'
       paymentTypeId:
         description: 鏀舵鏂瑰紡ID
         type: integer
+      principal:
+        allOf:
+        - $ref: '#/definitions/model.User'
+        description: 璐熻矗浜篿d
       principalId:
         description: 璐熻矗浜篿d
         type: integer
@@ -2261,8 +2421,9 @@
         description: 婧愬崟id
         type: integer
       sourceType:
+        allOf:
+        - $ref: '#/definitions/constvar.ReceiptSourceType'
         description: 鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級
-        type: integer
     type: object
   request.AddRefundMethod:
     properties:
@@ -3219,6 +3380,8 @@
     properties:
       keyword:
         type: string
+      keywordType:
+        $ref: '#/definitions/constvar.SalesRefundKeywordType'
       page:
         description: 椤电爜
         type: integer
@@ -3454,7 +3617,8 @@
     type: object
   request.SalesRefund:
     properties:
-      accountId:
+      bankAccountId:
+        description: 璐︽埛id
         type: integer
       clientId:
         type: integer
@@ -3464,6 +3628,9 @@
         type: integer
       number:
         type: string
+      paymentTypeId:
+        description: 鏀舵鏂瑰紡ID
+        type: integer
       products:
         items:
           $ref: '#/definitions/model.Product'
@@ -3472,8 +3639,13 @@
         type: string
       refundDate:
         type: string
-      refundMethod:
-        type: string
+      sourceId:
+        description: 婧愬崟id
+        type: integer
+      sourceType:
+        allOf:
+        - $ref: '#/definitions/constvar.RefundSourceType'
+        description: 鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級
     type: object
   request.SalesReturn:
     properties:
@@ -3484,17 +3656,28 @@
       number:
         type: string
       products:
+        description: 閫�璐т骇鍝�
         items:
           $ref: '#/definitions/model.Product'
         type: array
       reason:
+        description: 閫�璐у師鍥�
         type: string
       repository:
         type: string
       returnDate:
+        description: 閫�璐ф棩鏈�
         type: string
-      status:
+      salesReturnStatusId:
+        description: 閫�璐х姸鎬乮d
         type: integer
+      sourceId:
+        description: 婧愬崟id
+        type: integer
+      sourceType:
+        allOf:
+        - $ref: '#/definitions/constvar.SalesReturnSourceType'
+        description: 婧愬崟绫诲瀷锛�1閿�鍞槑缁嗭級
     type: object
   request.SetAuthorityMenu:
     properties:
@@ -4218,6 +4401,11 @@
     type: object
   request.UpdateReceipt:
     properties:
+      amount:
+        description: 鏀舵閲戦
+        type: number
+      bankAccount:
+        $ref: '#/definitions/model.BankAccount'
       bankAccountId:
         description: 璐︽埛id
         type: integer
@@ -4232,9 +4420,15 @@
       moneyType:
         description: 甯佺
         type: string
+      paymentType:
+        $ref: '#/definitions/model.PaymentType'
       paymentTypeId:
         description: 鏀舵鏂瑰紡ID
         type: integer
+      principal:
+        allOf:
+        - $ref: '#/definitions/model.User'
+        description: 璐熻矗浜篿d
       principalId:
         description: 璐熻矗浜篿d
         type: integer
@@ -4248,8 +4442,9 @@
         description: 婧愬崟id
         type: integer
       sourceType:
+        allOf:
+        - $ref: '#/definitions/constvar.ReceiptSourceType'
         description: 鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級
-        type: integer
     type: object
   request.UpdateRefundMethod:
     properties:
@@ -4590,6 +4785,15 @@
       amount:
         description: 閲戦
         type: number
+      amountReceivable:
+        description: 搴旀敹閲戦
+        type: number
+      amountReceived:
+        description: 宸叉敹閲戦
+        type: number
+      amountTotal:
+        description: 鎬婚
+        type: number
       collectionDate:
         description: 璁″垝鏀舵鏃ユ湡
         type: string
@@ -4617,12 +4821,13 @@
         description: 婧愬崟id
         type: integer
       sourceType:
+        allOf:
+        - $ref: '#/definitions/constvar.CollectionSourceType'
         description: 婧愬崟绫诲瀷锛�1閿�鍞槑缁�2鏈嶅姟鍚堝悓3閿�鍞彂绁級
-        type: integer
       status:
         allOf:
         - $ref: '#/definitions/constvar.CollectionStatus'
-        description: 鐘舵�侊紙1鏈敹2宸叉敹锛�
+        description: 鐘舵�侊紙1鏈敹2閮ㄥ垎宸叉敹3宸叉敹锛�
       term:
         description: 鏈熸
         type: integer
diff --git a/model/interface.go b/model/interface.go
index c7b70d4..2b8847d 100644
--- a/model/interface.go
+++ b/model/interface.go
@@ -6,8 +6,8 @@
 )
 
 type MoneyAdder interface {
-	AmountReceivableAdd(*gorm.DB, decimal.Decimal)
-	AmountReceivedAdd(*gorm.DB, decimal.Decimal)
-	AmountInvoicedAdd(*gorm.DB, decimal.Decimal)
-	AmountNotInvoicedAdd(*gorm.DB, decimal.Decimal)
+	AmountReceivableAdd(tx *gorm.DB, id int, amount decimal.Decimal) error
+	AmountReceivedAdd(tx *gorm.DB, id int, amount decimal.Decimal) error
+	AmountInvoicedAdd(tx *gorm.DB, id int, amount decimal.Decimal) error
+	AmountNotInvoicedAdd(tx *gorm.DB, id int, amount decimal.Decimal) error
 }
diff --git a/model/model.go b/model/model.go
index 5963906..b95cec5 100644
--- a/model/model.go
+++ b/model/model.go
@@ -1,6 +1,9 @@
 package model
 
-import "time"
+import (
+	"gorm.io/gorm"
+	"time"
+)
 
 // MyModel definitions from gorm.Model
 //
@@ -19,3 +22,17 @@
 	// example: 2023-08-10 15:48:25
 	DeletedAt *time.Time `json:"deleted_at,omitempty"`
 }
+
+type CrmModel struct {
+	gorm.Model  `json:"-"`
+	CreatorId   int       `json:"-" gorm:"column:creator_id;type:int;comment:鍒涘缓浜篿d"`
+	Creator     User      `json:"-"  gorm:"foreignKey:CreatorId"`
+	CreateTime  time.Time `json:"createTime"  gorm:"-"`
+	CreatorName string    `json:"creatorName" gorm:"-"`
+}
+
+func (slf *CrmModel) AfterFind(tx *gorm.DB) (err error) {
+	slf.CreatorName = slf.Creator.Username
+	slf.CreateTime = slf.CreatedAt
+	return nil
+}
diff --git a/model/receipt.go b/model/receipt.go
index 60d1d2a..c93385f 100644
--- a/model/receipt.go
+++ b/model/receipt.go
@@ -5,23 +5,29 @@
 	"aps_crm/pkg/mysqlx"
 	"errors"
 	"fmt"
+	"github.com/shopspring/decimal"
 	"gorm.io/gorm"
 )
 
 type (
 	// Receipt 鏀舵鍗�
 	Receipt struct {
-		Id            int    `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
-		ClientId      int    `gorm:"client_id" json:"clientId"`            // 瀹㈡埛id
-		SourceType    int    `gorm:"source_type" json:"sourceType"`        // 鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級
-		SourceId      int    `gorm:"source_id" json:"sourceId"`            // 婧愬崟id
-		PrincipalId   int    `gorm:"principal_id" json:"principalId"`      // 璐熻矗浜篿d
-		ReceiptDate   string `gorm:"receipt_date" json:"receiptDate"`      // 鏀舵鏃ユ湡
-		MoneyType     string `gorm:"money_type" json:"moneyType"`          // 甯佺
-		PaymentTypeId int    `gorm:"payment_type_id" json:"paymentTypeId"` // 鏀舵鏂瑰紡ID
-		BankAccountId int    `gorm:"bank_account_id" json:"bankAccountId"` // 璐︽埛id
-		Remark        string `gorm:"remark" json:"remark"`                 // 澶囨敞
-		FileId        int    `gorm:"file_id" json:"fileId"`                // 闄勪欢id
+		Id            int                        `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
+		ClientId      int                        `gorm:"column:client_id;type:int;not null;default 0;comment:瀹㈡埛id" json:"clientId"`                                // 瀹㈡埛id
+		SourceType    constvar.ReceiptSourceType `gorm:"column:source_type;type:int;not null;default 0;comment:鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級" json:"sourceType"` // 鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級
+		SourceId      int                        `gorm:"column:source_id;type:int;not null;default 0;comment:婧愬崟id " json:"sourceId"`                               // 婧愬崟id
+		PrincipalId   int                        `gorm:"column:principal_id;type:int;not null;default 0;comment:璐熻矗浜篿d" json:"principalId"`                         // 璐熻矗浜篿d
+		Principal     User                       `gorm:"foreignKey:PrincipalId" json:"principal"`                                                                  // 璐熻矗浜篿d
+		ReceiptDate   string                     `gorm:"column:receipt_date;type:varchar(255);not null;default '';comment:鏀舵鏃ユ湡" json:"receiptDate"`                // 鏀舵鏃ユ湡
+		MoneyType     string                     `gorm:"column:money_type;type:varchar(255);not null;default '';comment:甯佺" json:"moneyType"`                      // 甯佺
+		Amount        decimal.Decimal            `gorm:"column:amount;type:decimal(12,2);not null;default '0.00';comment:鏀舵閲戦" json:"amount"`                      // 鏀舵閲戦
+		PaymentTypeId int                        `gorm:"column:payment_type_id;type:int;not null;default 0;comment:鏀舵鏂瑰紡ID" json:"paymentTypeId"`                   // 鏀舵鏂瑰紡ID
+		PaymentType   PaymentType                `gorm:"foreignKey:PaymentTypeId" json:"paymentType"`
+		BankAccountId int                        `gorm:"column:bank_account_id;type:int;not null;default 0;comment:璐︽埛id" json:"bankAccountId"` // 璐︽埛id
+		BankAccount   BankAccount                `gorm:"foreignKey:BankAccountId" json:"bankAccount"`
+		Remark        string                     `gorm:"column:remark;type:varchar(255);not null;default '';comment:澶囨敞" json:"remark"` // 澶囨敞
+		FileId        int                        `gorm:"column:file_id;type:int;not null;default 0;comment:闄勪欢id" json:"fileId"`        // 闄勪欢id
+		gorm.Model    `json:"-"`
 	}
 
 	// ReceiptSearch 鏀舵鍗曟悳绱㈡潯浠�
diff --git a/model/request/salesDetails.go b/model/request/salesDetails.go
index 1d12f61..7758bf6 100644
--- a/model/request/salesDetails.go
+++ b/model/request/salesDetails.go
@@ -10,23 +10,23 @@
 }
 
 type SalesDetails struct {
-	ClientId            int             `json:"clientId" gorm:"column:client_id;type:int;comment:瀹㈡埛id"`
-	Number              string          `json:"number" gorm:"column:number;type:varchar(255);comment:閿�鍞瓙鍗曞彿"`
-	SaleChanceId        int             `json:"saleChanceId" gorm:"column:sale_chance_id;type:int;comment:閿�鍞満浼歩d"`
-	SaleType            int             `json:"saleType" gorm:"column:sale_type;type:int;comment:閿�鍞被鍨�"`
-	SignTime            string          `json:"signTime" gorm:"column:sign_time;type:datetime;comment:绛惧崟鏃堕棿"`
-	MemberId            int             `json:"memberId" gorm:"column:member_id;type:int;comment:璐熻矗浜篿d"`
-	DeliveryDate        string          `json:"deliveryDate" gorm:"column:delivery_date;type:datetime;comment:浜よ揣鏃ユ湡"`
-	WechatOrderStatusId int             `json:"wechatOrderStatusId" gorm:"column:wechat_order_status_id;type:int;comment:寰俊璁㈠崟鐘舵�乮d"`
-	Address             string          `json:"address" gorm:"column:address;type:varchar(255);comment:鍦板潃"`
-	Phone               string          `json:"phone" gorm:"column:phone;type:varchar(255);comment:鐢佃瘽"`
-	Addressee           string          `json:"addressee" gorm:"column:addressee;type:varchar(255);comment:鏀朵欢浜�"`
-	Conditions          string          `json:"conditions" gorm:"column:conditions;type:text;comment:鏉′欢"`
-	Remark              string          `json:"remark" gorm:"column:remark;type:text;comment:澶囨敞"`
-	Products            []model.Product `json:"products" gorm:"many2many:sales_details_product;"`
-	LogisticCompany     string          `json:"logisticCompany" gorm:"column:logistic_company;type:varchar(255);comment:鐗╂祦鍏徃"`
-	LogisticNumber      string          `json:"logisticNumber" gorm:"column:logistic_number;type:varchar(255);comment:鐗╂祦鍗曞彿"`
-	LogisticCost        float64         `json:"logisticCost" gorm:"column:logistic_cost;type:decimal(10,2);comment:鐗╂祦璐圭敤"`
+	ClientId            int              `json:"clientId" gorm:"column:client_id;type:int;comment:瀹㈡埛id"`
+	Number              string           `json:"number" gorm:"column:number;type:varchar(255);comment:閿�鍞瓙鍗曞彿"`
+	SaleChanceId        int              `json:"saleChanceId" gorm:"column:sale_chance_id;type:int;comment:閿�鍞満浼歩d"`
+	SaleType            int              `json:"saleType" gorm:"column:sale_type;type:int;comment:閿�鍞被鍨�"`
+	SignTime            string           `json:"signTime" gorm:"column:sign_time;type:datetime;comment:绛惧崟鏃堕棿"`
+	MemberId            int              `json:"memberId" gorm:"column:member_id;type:int;comment:璐熻矗浜篿d"`
+	DeliveryDate        string           `json:"deliveryDate" gorm:"column:delivery_date;type:datetime;comment:浜よ揣鏃ユ湡"`
+	WechatOrderStatusId int              `json:"wechatOrderStatusId" gorm:"column:wechat_order_status_id;type:int;comment:寰俊璁㈠崟鐘舵�乮d"`
+	Address             string           `json:"address" gorm:"column:address;type:varchar(255);comment:鍦板潃"`
+	Phone               string           `json:"phone" gorm:"column:phone;type:varchar(255);comment:鐢佃瘽"`
+	Addressee           string           `json:"addressee" gorm:"column:addressee;type:varchar(255);comment:鏀朵欢浜�"`
+	Conditions          string           `json:"conditions" gorm:"column:conditions;type:text;comment:鏉′欢"`
+	Remark              string           `json:"remark" gorm:"column:remark;type:text;comment:澶囨敞"`
+	Products            []*model.Product `json:"products" gorm:"many2many:sales_details_product;"`
+	LogisticCompany     string           `json:"logisticCompany" gorm:"column:logistic_company;type:varchar(255);comment:鐗╂祦鍏徃"`
+	LogisticNumber      string           `json:"logisticNumber" gorm:"column:logistic_number;type:varchar(255);comment:鐗╂祦鍗曞彿"`
+	LogisticCost        float64          `json:"logisticCost" gorm:"column:logistic_cost;type:decimal(10,2);comment:鐗╂祦璐圭敤"`
 }
 
 type UpdateSalesDetails struct {
diff --git a/model/request/salesRefund.go b/model/request/salesRefund.go
index 04b792b..5f54725 100644
--- a/model/request/salesRefund.go
+++ b/model/request/salesRefund.go
@@ -1,21 +1,26 @@
 package request
 
-import "aps_crm/model"
+import (
+	"aps_crm/constvar"
+	"aps_crm/model"
+)
 
 type AddSalesRefundRequest struct {
 	SalesRefund SalesRefund `json:"salesRefund"`
 }
 
 type SalesRefund struct {
-	ClientId     int             `json:"clientId"`
-	Number       string          `json:"number"`
-	MemberId     int             `json:"memberId"`
-	RefundDate   string          `json:"refundDate"`
-	RefundMethod string          `json:"refundMethod"`
-	AccountId    int             `json:"accountId"`
-	IsInvoice    int             `json:"isInvoice"`
-	Reason       string          `json:"reason"`
-	Products     []model.Product `json:"products"`
+	ClientId      int                       `json:"clientId"`
+	Number        string                    `json:"number"`
+	MemberId      int                       `json:"memberId"`
+	SourceType    constvar.RefundSourceType `gorm:"column:source_type;type:int;not null;default 0;comment:鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級" json:"sourceType"` // 鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級
+	SourceId      int                       `gorm:"column:source_id;type:int;not null;default 0;comment:婧愬崟id " json:"sourceId"`                               // 婧愬崟id
+	RefundDate    string                    `json:"refundDate"`
+	PaymentTypeId int                       `gorm:"column:payment_type_id;type:int;not null;default 0;comment:鏀舵鏂瑰紡ID" json:"paymentTypeId"` // 鏀舵鏂瑰紡ID
+	BankAccountId int                       `gorm:"column:bank_account_id;type:int;not null;default 0;comment:璐︽埛id" json:"bankAccountId"`   // 璐︽埛id
+	IsInvoice     int                       `json:"isInvoice"`
+	Reason        string                    `json:"reason"`
+	Products      []*model.Product          `json:"products"`
 }
 
 type UpdateSalesRefundRequest struct {
@@ -25,5 +30,6 @@
 
 type GetSalesRefundList struct {
 	PageInfo
-	Keyword string `json:"keyword"`
+	Keyword     string `json:"keyword"`
+	KeywordType constvar.SalesRefundKeywordType
 }
diff --git a/model/request/salesReturn.go b/model/request/salesReturn.go
index a31794c..8da7dbc 100644
--- a/model/request/salesReturn.go
+++ b/model/request/salesReturn.go
@@ -1,20 +1,27 @@
 package request
 
-import "aps_crm/model"
+import (
+	"aps_crm/constvar"
+	"aps_crm/model"
+)
 
 type AddSalesReturnRequest struct {
 	SalesReturn SalesReturn
 }
 
 type SalesReturn struct {
-	ClientId   int             `json:"clientId" gorm:"column:client_id;type:int;comment:瀹㈡埛id"`
-	Number     string          `json:"number" gorm:"column:number;type:varchar(255);comment:閫�璐у崟鍙�"`
-	Repository string          `json:"repository" gorm:"column:repository;type:varchar(255);comment:浠撳簱"`
-	MemberId   int             `json:"memberId" gorm:"column:member_id;type:int;comment:璐熻矗浜篿d"`
-	ReturnDate string          `json:"returnDate" gorm:"column:return_date;type:datetime;comment:閫�璐ф棩鏈�"`
-	Status     int             `json:"status" gorm:"column:status;type:int;comment:閫�璐х姸鎬�"`
-	Reason     string          `json:"reason" gorm:"column:reason;type:varchar(255);comment:閫�璐у師鍥�"`
-	Products   []model.Product `json:"products" gorm:"many2many:salesReturn_product;"`
+	ClientId            int                            `json:"clientId" gorm:"column:client_id;type:int;comment:瀹㈡埛id"`
+	SourceType          constvar.SalesReturnSourceType `gorm:"source_type" json:"sourceType"` // 婧愬崟绫诲瀷锛�1閿�鍞槑缁嗭級
+	SourceId            int                            `gorm:"source_id" json:"sourceId"`     // 婧愬崟id
+	Number              string                         `json:"number" gorm:"column:number;type:varchar(255);comment:閫�璐у崟鍙�"`
+	Repository          string                         `json:"repository" gorm:"column:repository;type:varchar(255);comment:浠撳簱"`
+	MemberId            int                            `json:"memberId" gorm:"column:member_id;type:int;comment:璐熻矗浜篿d"`
+	ReturnDate          string                         `json:"returnDate" gorm:"column:return_date;type:datetime(3);comment:閫�璐ф棩鏈�"`          //閫�璐ф棩鏈�
+	SalesReturnStatusId int                            `json:"salesReturnStatusId" gorm:"column:sales_return_status;type:int;comment:閫�璐х姸鎬�"` //閫�璐х姸鎬乮d
+	CreatorId           int                            `json:"-" gorm:"column:creator_id;type:int;comment:鍒涘缓浜篿d"`                           //鍒涘缓浜篒D
+	Creator             User                           `json:"-"  gorm:"foreignKey:CreatorId"`                                              //鍒涘缓浜轰俊鎭�
+	Reason              string                         `json:"reason" gorm:"column:reason;type:varchar(255);comment:閫�璐у師鍥�"`                  //閫�璐у師鍥�
+	Products            []*model.Product               `json:"products" gorm:"many2many:salesReturn_product;"`                              //閫�璐т骇鍝�
 }
 
 type UpdateSalesReturnRequest struct {
diff --git a/model/salesDetails.go b/model/salesDetails.go
index b318ab7..be63cf7 100644
--- a/model/salesDetails.go
+++ b/model/salesDetails.go
@@ -20,6 +20,7 @@
 		SaleType            int               `json:"saleType" gorm:"column:sale_type;type:int;comment:閿�鍞被鍨�"`
 		SignTime            string            `json:"signTime" gorm:"column:sign_time;type:varchar(255);comment:绛惧崟鏃堕棿"`
 		MemberId            int               `json:"memberId" gorm:"column:member_id;type:int;comment:璐熻矗浜篿d"`
+		Member              User              `json:"Member"  gorm:"foreignKey:MemberId"`
 		DeliveryDate        string            `json:"deliveryDate" gorm:"column:delivery_date;type:varchar(255);comment:浜よ揣鏃ユ湡"`
 		WechatOrderStatusId int               `json:"wechatOrderStatusId" gorm:"column:wechat_order_status;type:int;comment:寰俊璁㈠崟鐘舵��"`
 		WechatOrderStatus   WechatOrderStatus `json:"wechatOrderStatus" gorm:"foreignKey:WechatOrderStatusId"`
@@ -27,16 +28,18 @@
 		Phone               string            `json:"phone" gorm:"column:phone;type:varchar(255);comment:鐢佃瘽"`
 		Addressee           string            `json:"addressee" gorm:"column:addressee;type:varchar(255);comment:鏀朵欢浜�"`
 		Conditions          string            `json:"conditions" gorm:"column:conditions;type:text;comment:鏉′欢"`
+		CreatorId           int               `json:"creatorId" gorm:"column:creator_id;type:int;comment:鍒涘缓浜篿d"`
 		Remark              string            `json:"remark" gorm:"column:remark;type:text;comment:澶囨敞"`
-		Products            []Product         `json:"products" gorm:"many2many:sales_details_product;"`
+		Products            []*Product        `json:"products" gorm:"many2many:sales_details_product;"`
 		LogisticCompany     string            `json:"logisticCompany" gorm:"column:logistic_company;type:varchar(255);comment:鐗╂祦鍏徃"`
 		LogisticNumber      string            `json:"logisticNumber" gorm:"column:logistic_number;type:varchar(255);comment:鐗╂祦鍗曞彿"`
 		LogisticCost        float64           `json:"logisticCost" gorm:"column:logistic_cost;type:decimal(10,2);comment:鐗╂祦璐圭敤"`
-		AmountReceivable    decimal.Decimal   `gorm:"amount_receivable" json:"amountReceivable"` // 搴旀敹閲戦
-		AmountReceived      decimal.Decimal   `gorm:"amount_received" json:"amountReceived"`     // 宸叉敹閲戦
-		AmountInvoiced      decimal.Decimal   `gorm:"amount_invoiced" json:"amountInvoiced"`     // 宸插紑绁ㄩ噾棰�
-		AmountUnInvoiced    decimal.Decimal   `gorm:"-" json:"amountUnInvoiced"`                 // 鏈紑绁ㄩ噾棰�
-		gorm.Model          `json:"-"`
+		AmountReceivable    decimal.Decimal   `gorm:"column:amount_receivable;type:decimal(12,2);comment:搴旀敹閲戦" json:"amountReceivable"`    // 搴旀敹閲戦
+		AmountReceived      decimal.Decimal   `gorm:"column:amount_received;type:decimal(12,2);comment:宸叉敹閲戦" json:"amountReceived"`        // 宸叉敹閲戦
+		AmountInvoiced      decimal.Decimal   `gorm:"column:amount_invoiced;type:decimal(12,2);comment:宸插紑绁ㄩ噾棰�" json:"amountInvoiced"`       // 宸插紑绁ㄩ噾棰�
+		AmountUnInvoiced    decimal.Decimal   `gorm:"column:amount_not_invoiced;type:decimal(12,2);comment:鏈紑绁ㄩ噾棰�" json:"amountUnInvoiced"` // 鏈紑绁ㄩ噾棰�
+		AmountTotal         decimal.Decimal   `gorm:"column:amount_total;type:decimal(12,2);comment:浠风◣鍚堣" json:"amountTotal"`              // 浠风◣鍚堣
+		CrmModel
 	}
 
 	SalesDetailsSearch struct {
@@ -111,7 +114,7 @@
 	return slf
 }
 
-func (slf *SalesDetailsSearch) Find() (*SalesDetails, error) {
+func (slf *SalesDetailsSearch) First() (*SalesDetails, error) {
 	var db = slf.build()
 	var record = new(SalesDetails)
 	err := db.First(record).Error
@@ -161,3 +164,57 @@
 	slf.OrderBy = order
 	return slf
 }
+
+func (slf *SalesDetailsSearch) UpdateByMap(upMap map[string]interface{}) error {
+	var (
+		db = slf.build()
+	)
+
+	if err := db.Updates(upMap).Error; err != nil {
+		return fmt.Errorf("update by map err: %v, upMap: %+v", err, upMap)
+	}
+
+	return nil
+}
+
+func (slf *SalesDetailsSearch) SetOrm(tx *gorm.DB) *SalesDetailsSearch {
+	slf.Orm = tx
+	return slf
+}
+
+func (slf *SalesDetailsSearch) AmountReceivableAdd(tx *gorm.DB, id int, amount decimal.Decimal) error {
+	slf.Orm = tx
+	record, err := slf.SetId(id).First()
+	if err != nil {
+		return err
+	}
+	amount = record.AmountReceivable.Add(amount)
+	return slf.UpdateByMap(map[string]interface{}{"amount_receivable": amount})
+}
+func (slf *SalesDetailsSearch) AmountReceivedAdd(tx *gorm.DB, id int, amount decimal.Decimal) error {
+	slf.Orm = tx
+	record, err := slf.SetId(id).First()
+	if err != nil {
+		return err
+	}
+	amount = record.AmountReceived.Add(amount)
+	return slf.UpdateByMap(map[string]interface{}{"amount_received": amount})
+}
+func (slf *SalesDetailsSearch) AmountInvoicedAdd(tx *gorm.DB, id int, amount decimal.Decimal) error {
+	slf.Orm = tx
+	record, err := slf.SetId(id).First()
+	if err != nil {
+		return err
+	}
+	amount = record.AmountInvoiced.Add(amount)
+	return slf.UpdateByMap(map[string]interface{}{"amount_invoiced": amount})
+}
+func (slf *SalesDetailsSearch) AmountNotInvoicedAdd(tx *gorm.DB, id int, amount decimal.Decimal) error {
+	slf.Orm = tx
+	record, err := slf.SetId(id).First()
+	if err != nil {
+		return err
+	}
+	amount = record.AmountUnInvoiced.Add(amount)
+	return slf.UpdateByMap(map[string]interface{}{"amount_not_invoiced": amount})
+}
diff --git a/model/salesRefund.go b/model/salesRefund.go
index cbdf41b..0d942a0 100644
--- a/model/salesRefund.go
+++ b/model/salesRefund.go
@@ -1,33 +1,45 @@
 package model
 
 import (
+	"aps_crm/constvar"
 	"aps_crm/pkg/mysqlx"
+	"fmt"
+	"github.com/shopspring/decimal"
 	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
 )
 
 type (
 	SalesRefund struct {
-		Id           int         `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
-		ClientId     int         `json:"clientId" gorm:"column:client_id;type:int;comment:瀹㈡埛id"`
-		Number       string      `json:"number" gorm:"column:number;type:varchar(255);comment:閫�娆惧崟鍙�"`
-		MemberId     int         `json:"memberId" gorm:"column:member_id;type:int;comment:璐熻矗浜篿d"`
-		RefundDate   *CustomTime `json:"refundDate" gorm:"column:refund_date;type:datetime;comment:閫�娆炬棩鏈�"`
-		RefundMethod string      `json:"refundMethod" gorm:"column:refund_method;type:varchar(255);comment:閫�娆炬柟寮�"`
-		AccountId    int         `json:"accountId" gorm:"column:account_id;type:int;comment:璐︽埛"`
-		IsInvoice    int         `json:"isInvoice" gorm:"column:is_invoice;type:int;comment:鏄惁寮�绁�"`
-		Reason       string      `json:"reason" gorm:"column:reason;type:varchar(255);comment:閫�娆惧師鍥�"`
-		Products     []Product   `json:"products" gorm:"many2many:salesRefund_product;"`
-		gorm.Model   `json:"-"`
+		Id            int                       `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
+		ClientId      int                       `json:"clientId" gorm:"column:client_id;type:int;comment:瀹㈡埛id"`
+		Client        Client                    `json:"client" gorm:"foreignKey:ClientId"`
+		Number        string                    `json:"number" gorm:"column:number;type:varchar(255);comment:閫�娆惧崟鍙�"`
+		SourceType    constvar.RefundSourceType `gorm:"column:source_type;type:int;not null;default 0;comment:鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級" json:"sourceType"` // 鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級
+		SourceId      int                       `gorm:"column:source_id;type:int;not null;default 0;comment:婧愬崟id " json:"sourceId"`                               // 婧愬崟id
+		MemberId      int                       `json:"memberId" gorm:"column:member_id;type:int;comment:璐熻矗浜篿d"`
+		Member        User                      `json:"member" gorm:"foreignKey:MemberId"`
+		RefundDate    string                    `json:"refundDate" gorm:"column:refund_date;type:datetime;comment:閫�娆炬棩鏈�"`
+		PaymentTypeId int                       `gorm:"column:payment_type_id;type:int;not null;default 0;comment:鏀舵鏂瑰紡ID" json:"paymentTypeId"` // 鏀舵鏂瑰紡ID
+		PaymentType   PaymentType               `gorm:"foreignKey:PaymentTypeId" json:"paymentType"`
+		BankAccountId int                       `gorm:"column:bank_account_id;type:int;not null;default 0;comment:璐︽埛id" json:"bankAccountId"` // 璐︽埛id
+		BankAccount   BankAccount               `gorm:"foreignKey:BankAccountId" json:"bankAccount"`
+		IsInvoice     int                       `json:"isInvoice" gorm:"column:is_invoice;type:int;comment:鏄惁寮�绁�"`
+		Reason        string                    `json:"reason" gorm:"column:reason;type:varchar(255);comment:閫�娆惧師鍥�"`
+		Products      []*Product                `json:"products" gorm:"many2many:salesRefund_product;"`
+		AmountTotal   decimal.Decimal           `gorm:"column:amount_total;type:decimal(12,2);comment:浠风◣鍚堣" json:"amountTotal"` // 浠风◣鍚堣
+		CrmModel
 	}
 
 	SalesRefundSearch struct {
 		SalesRefund
-
-		Orm      *gorm.DB
-		Keyword  string
-		OrderBy  string
-		PageNum  int
-		PageSize int
+		Orm         *gorm.DB
+		KeywordType constvar.SalesRefundKeywordType
+		Keyword     string
+		OrderBy     string
+		PageNum     int
+		PageSize    int
+		Preload     bool
 	}
 )
 
@@ -43,11 +55,38 @@
 
 func (slf *SalesRefundSearch) build() *gorm.DB {
 	var db = slf.Orm.Model(&SalesRefund{})
-	if slf.Keyword != "" {
-		db = db.Where("name LIKE ?", "%"+slf.Keyword+"%")
-	}
 	if slf.Id != 0 {
 		db = db.Where("id = ?", slf.Id)
+	}
+
+	if slf.Preload {
+		db = db.Preload("Client").
+			Preload("PaymentType").
+			Preload("BankAccount").
+			Preload("Products")
+	}
+	if slf.KeywordType != "" {
+		switch slf.KeywordType {
+		case constvar.SalesRefundKeywordRefundNumber:
+			db = db.Where("number like ?", fmt.Sprintf("%%%s%%", slf.Keyword))
+		case constvar.SalesRefundKeywordClientName:
+			db = db.Joins("Client", clause.LeftJoin).Where("Client.name like ?", fmt.Sprintf("%%%s%%", slf.Keyword))
+		case constvar.SalesRefundKeywordRefundDate:
+			db = db.Where("refund_date like ?", fmt.Sprintf("%%%s%%", slf.Keyword))
+		case constvar.SalesRefundKeywordAccount:
+			db = db.Joins("BankAccount").Where("BankAccount name like ?", fmt.Sprintf("%%%s%%", slf.Keyword))
+		case constvar.SalesRefundKeywordIsInvoice:
+			db = db.Where("is_invoice like ?", fmt.Sprintf("%%%s%%", slf.Keyword))
+		case constvar.SalesRefundKeywordPaymentType:
+			db = db.Joins("PaymentType").Where("PaymentType.name like ?", fmt.Sprintf("%%%s%%", slf.Keyword))
+		case constvar.SalesRefundKeywordPrincipal:
+			db = db.Joins("left join user on user.id = sales_refund.member_id").Where("user.username like ?", fmt.Sprintf("%%%s%%", slf.Keyword))
+		case constvar.SalesRefundKeywordUpdateAt:
+			db = db.Where("updated_at like ?", fmt.Sprintf("%%%s%%", slf.Keyword))
+		case constvar.SalesRefundKeywordPriceTotal:
+			db = db.Where("amount_total like ?", fmt.Sprintf("%%%s%%", slf.Keyword))
+
+		}
 	}
 
 	return db
@@ -99,6 +138,16 @@
 	return slf
 }
 
+func (slf *SalesRefundSearch) SetPreload(preload bool) *SalesRefundSearch {
+	slf.Preload = preload
+	return slf
+}
+
+func (slf *SalesRefundSearch) SetKeywordType(keywordType constvar.SalesRefundKeywordType) *SalesRefundSearch {
+	slf.KeywordType = keywordType
+	return slf
+}
+
 func (slf *SalesRefundSearch) SetKeyword(keyword string) *SalesRefundSearch {
 	slf.Keyword = keyword
 	return slf
diff --git a/model/salesReturn.go b/model/salesReturn.go
index 646ca70..d4a64a7 100644
--- a/model/salesReturn.go
+++ b/model/salesReturn.go
@@ -1,21 +1,30 @@
 package model
 
 import (
+	"aps_crm/constvar"
 	"aps_crm/pkg/mysqlx"
 	"gorm.io/gorm"
 )
 
 type (
 	SalesReturn struct {
-		Id                int         `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
-		ClientId          int         `json:"clientId" gorm:"column:client_id;type:int;comment:瀹㈡埛id"`
-		Number            string      `json:"number" gorm:"column:number;type:varchar(255);comment:閫�璐у崟鍙�"`
-		Repository        string      `json:"repository" gorm:"column:repository;type:varchar(255);comment:浠撳簱"`
-		MemberId          int         `json:"memberId" gorm:"column:member_id;type:int;comment:璐熻矗浜篿d"`
-		ReturnDate        *CustomTime `json:"returnDate" gorm:"column:return_date;type:datetime;comment:閫�璐ф棩鏈�"`
-		SalesReturnStatus int         `json:"salesReturnStatus" gorm:"column:sales_return_status;type:int;comment:閫�璐х姸鎬�"`
-		Reason            string      `json:"reason" gorm:"column:reason;type:varchar(255);comment:閫�璐у師鍥�"`
-		Products          []Product   `json:"products" gorm:"many2many:salesReturn_product;"`
+		Id                  int                            `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
+		ClientId            int                            `json:"clientId" gorm:"column:client_id;type:int;comment:瀹㈡埛id"`
+		Client              Client                         `json:"client" gorm:"foreignKey:ClientId"`
+		SourceType          constvar.SalesReturnSourceType `gorm:"source_type" json:"sourceType"` // 婧愬崟绫诲瀷锛�1閿�鍞槑缁嗭級
+		SourceId            int                            `gorm:"source_id" json:"sourceId"`     // 婧愬崟id
+		Number              string                         `json:"number" gorm:"column:number;type:varchar(255);comment:閫�璐у崟鍙�"`
+		Repository          string                         `json:"repository" gorm:"column:repository;type:varchar(255);comment:浠撳簱"`
+		MemberId            int                            `json:"memberId" gorm:"column:member_id;type:int;comment:璐熻矗浜篿d"`
+		Member              User                           `json:"Member"  gorm:"foreignKey:MemberId"`
+		ReturnDate          string                         `json:"returnDate" gorm:"column:return_date;type:datetime(3);comment:閫�璐ф棩鏈�"`          //閫�璐ф棩鏈�
+		SalesReturnStatusId int                            `json:"salesReturnStatusId" gorm:"column:sales_return_status;type:int;comment:閫�璐х姸鎬�"` //閫�璐х姸鎬乮d
+		SalesReturnStatus   SalesReturnStatus              `json:"SalesReturnStatus" gorm:"foreignKey:SalesReturnStatusId"`                     //閫�璐х姸鎬�
+		CreatorId           int                            `json:"-" gorm:"column:creator_id;type:int;comment:鍒涘缓浜篿d"`                           //鍒涘缓浜篒D
+		Creator             User                           `json:"-"  gorm:"foreignKey:CreatorId"`                                              //鍒涘缓浜轰俊鎭�
+		Reason              string                         `json:"reason" gorm:"column:reason;type:varchar(255);comment:閫�璐у師鍥�"`                  //閫�璐у師鍥�
+		Products            []*Product                     `json:"products" gorm:"many2many:salesReturn_product;"`                              //閫�璐т骇鍝�
+		CrmModel
 	}
 
 	SalesReturnSearch struct {
@@ -29,10 +38,9 @@
 	}
 )
 
-func (SalesReturn) TableName() string {
+func (*SalesReturn) TableName() string {
 	return "sales_return"
 }
-
 func NewSalesReturnSearch() *SalesReturnSearch {
 	return &SalesReturnSearch{
 		Orm: mysqlx.GetDB(),
diff --git a/model/salesReturnStatus.go b/model/salesReturnStatus.go
index 8f3d538..10d15d9 100644
--- a/model/salesReturnStatus.go
+++ b/model/salesReturnStatus.go
@@ -6,12 +6,12 @@
 )
 
 type (
-	// SalesReturnStatus 鍟嗘満闃舵
+	// SalesReturnStatus 閫�璐х姸鎬�
 	SalesReturnStatus struct {
 		Id   int    `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
-		Name string `json:"name" gorm:"column:name;type:varchar(255);comment:鍟嗘満闃舵鍚嶇О"`
+		Name string `json:"name" gorm:"column:name;type:varchar(255);comment:閫�璐х姸鎬佸悕绉�"`
 	}
-   
+
 	SalesReturnStatusSearch struct {
 		SalesReturnStatus
 		Orm *gorm.DB
diff --git a/model/serviceCollectionPlan.go b/model/serviceCollectionPlan.go
index cb15770..cfe065c 100644
--- a/model/serviceCollectionPlan.go
+++ b/model/serviceCollectionPlan.go
@@ -13,19 +13,22 @@
 type (
 	// ServiceCollectionPlan 鏀舵璁″垝
 	ServiceCollectionPlan struct {
-		Id             int                       `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
-		CollectionType int                       `gorm:"collection_type" json:"collectionType"` // 绫诲瀷锛�1 璁″垝鏀舵鏃ユ湡 2 椤圭洰鐘舵�侊級
-		SourceType     int                       `gorm:"source_type" json:"sourceType"`         // 婧愬崟绫诲瀷锛�1閿�鍞槑缁�2鏈嶅姟鍚堝悓3閿�鍞彂绁級
-		SourceId       int                       `gorm:"source_id" json:"sourceId"`             // 婧愬崟id
-		PrincipalId    int                       `gorm:"principal_id" json:"principalId"`       // 鏀舵璐熻矗浜篒D
-		Term           int                       `gorm:"term" json:"term"`                      // 鏈熸
-		Percent        decimal.Decimal           `gorm:"percent" json:"percent"`                // 姣斾緥
-		Amount         decimal.Decimal           `gorm:"amount" json:"amount"`                  // 閲戦
-		MoneyType      string                    `gorm:"money_type" json:"moneyType"`           // 甯佺
-		CollectionDate time.Time                 `gorm:"collection_date" json:"collectionDate"` // 璁″垝鏀舵鏃ユ湡
-		Remark         string                    `gorm:"remark" json:"remark"`                  // 澶囨敞
-		Status         constvar.CollectionStatus `gorm:"status" json:"status"`                  // 鐘舵�侊紙1鏈敹2宸叉敹锛�
-		FileId         int                       `gorm:"file_id" json:"fileId"`                 // 闄勪欢id
+		Id               int                           `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
+		CollectionType   int                           `gorm:"collection_type" json:"collectionType"`                                            // 绫诲瀷锛�1 璁″垝鏀舵鏃ユ湡 2 椤圭洰鐘舵�侊級
+		SourceType       constvar.CollectionSourceType `gorm:"source_type" json:"sourceType"`                                                    // 婧愬崟绫诲瀷锛�1閿�鍞槑缁�2鏈嶅姟鍚堝悓3閿�鍞彂绁級
+		SourceId         int                           `gorm:"source_id" json:"sourceId"`                                                        // 婧愬崟id
+		PrincipalId      int                           `gorm:"principal_id" json:"principalId"`                                                  // 鏀舵璐熻矗浜篒D
+		Term             int                           `gorm:"term" json:"term"`                                                                 // 鏈熸
+		Percent          decimal.Decimal               `gorm:"percent" json:"percent"`                                                           // 姣斾緥
+		Amount           decimal.Decimal               `gorm:"amount" json:"amount"`                                                             // 閲戦
+		MoneyType        string                        `gorm:"money_type" json:"moneyType"`                                                      // 甯佺
+		CollectionDate   time.Time                     `gorm:"collection_date" json:"collectionDate"`                                            // 璁″垝鏀舵鏃ユ湡
+		Remark           string                        `gorm:"remark" json:"remark"`                                                             // 澶囨敞
+		Status           constvar.CollectionStatus     `gorm:"status" json:"status"`                                                             // 鐘舵�侊紙1鏈敹2閮ㄥ垎宸叉敹3宸叉敹锛�
+		AmountReceivable decimal.Decimal               `gorm:"column:amount_receivable;type:decimal(12,2);comment:搴旀敹閲戦" json:"amountReceivable"` // 搴旀敹閲戦
+		AmountReceived   decimal.Decimal               `gorm:"column:amount_received;type:decimal(12,2);comment:宸叉敹閲戦" json:"amountReceived"`     // 宸叉敹閲戦
+		AmountTotal      decimal.Decimal               `gorm:"column:amount_total;type:decimal(12,2);comment:鎬婚" json:"amountTotal"`             // 鎬婚
+		FileId           int                           `gorm:"file_id" json:"fileId"`                                                            // 闄勪欢id
 	}
 
 	// ServiceCollectionPlanSearch 鏀舵璁″垝鎼滅储鏉′欢
@@ -145,6 +148,38 @@
 	return records, total, err
 }
 
+func (slf *ServiceCollectionPlanSearch) UpdateByMap(upMap map[string]interface{}) error {
+	var (
+		db = slf.build()
+	)
+
+	if err := db.Updates(upMap).Error; err != nil {
+		return fmt.Errorf("update by map err: %v, upMap: %+v", err, upMap)
+	}
+
+	return nil
+}
+
+func (slf *ServiceCollectionPlanSearch) UpdateStatusAndAmount(collection *ServiceCollectionPlan, receiveAmount decimal.Decimal) error {
+	receivedAmount := collection.AmountReceived.Add(receiveAmount)
+	var status constvar.CollectionStatus
+	if receiveAmount.GreaterThanOrEqual(collection.AmountTotal) {
+		status = constvar.CollectionStatusCollected
+	} else {
+		status = constvar.CollectionStatusSubCollected
+	}
+	receivableAmount := collection.AmountTotal.Add(receivedAmount)
+	err := slf.SetId(collection.Id).UpdateByMap(map[string]interface{}{
+		"status":            status,
+		"amount_received":   receivedAmount,
+		"amount_receivable": receivableAmount})
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
 // InitDefaultData 鍒濆鍖栨暟鎹�
 func (slf *ServiceCollectionPlanSearch) InitDefaultData() error {
 	var (
diff --git a/model/serviceContract.go b/model/serviceContract.go
index 94acee1..05eed61 100644
--- a/model/serviceContract.go
+++ b/model/serviceContract.go
@@ -35,10 +35,11 @@
 		ServiceTimes            int                   `json:"serviceTimes" gorm:"column:service_times;type:int;comment:鏈嶅姟娆℃暟"`
 		Terms                   string                `json:"terms" gorm:"column:terms;type:text;comment:鏉℃"`
 		Remark                  string                `json:"remark" gorm:"column:remark;type:text;comment:澶囨敞"`
-		AmountReceivable        decimal.Decimal       `gorm:"amount_receivable" json:"amountReceivable"` // 搴旀敹閲戦
-		AmountReceived          decimal.Decimal       `gorm:"amount_received" json:"amountReceived"`     // 宸叉敹閲戦
-		AmountInvoiced          decimal.Decimal       `gorm:"amount_invoiced" json:"amountInvoiced"`     // 宸插紑绁ㄩ噾棰�
-		AmountUnInvoiced        decimal.Decimal       `gorm:"-" json:"amountUnInvoiced"`                 // 鏈紑绁ㄩ噾棰�
+		AmountReceivable        decimal.Decimal       `gorm:"column:amount_receivable;type:decimal(12,2);comment:搴旀敹閲戦" json:"amountReceivable"`    // 搴旀敹閲戦
+		AmountReceived          decimal.Decimal       `gorm:"column:amount_received;type:decimal(12,2);comment:宸叉敹閲戦" json:"amountReceived"`        // 宸叉敹閲戦
+		AmountInvoiced          decimal.Decimal       `gorm:"column:amount_invoiced;type:decimal(12,2);comment:宸插紑绁ㄩ噾棰�" json:"amountInvoiced"`       // 宸插紑绁ㄩ噾棰�
+		AmountUnInvoiced        decimal.Decimal       `gorm:"column:amount_not_invoiced;type:decimal(12,2);comment:鏈紑绁ㄩ噾棰�" json:"amountUnInvoiced"` // 鏈紑绁ㄩ噾棰�
+		AmountTotal             decimal.Decimal       `gorm:"column:amount_total;type:decimal(12,2);comment:浠风◣鍚堣" json:"amountTotal"`              // 浠风◣鍚堣
 		Products                []*Product            `json:"products" gorm:"many2many:service_contract_product;"`
 		gorm.Model              `json:"-"`
 	}
@@ -216,3 +217,40 @@
 
 	return record, nil
 }
+
+func (slf *ServiceContractSearch) AmountReceivableAdd(tx *gorm.DB, id int, amount decimal.Decimal) error {
+	slf.Orm = tx
+	record, err := slf.SetId(id).First()
+	if err != nil {
+		return err
+	}
+	amount = record.AmountReceivable.Add(amount)
+	return slf.UpdateByMap(map[string]interface{}{"amount_receivable": amount})
+}
+func (slf *ServiceContractSearch) AmountReceivedAdd(tx *gorm.DB, id int, amount decimal.Decimal) error {
+	slf.Orm = tx
+	record, err := slf.SetId(id).First()
+	if err != nil {
+		return err
+	}
+	amount = record.AmountReceived.Add(amount)
+	return slf.UpdateByMap(map[string]interface{}{"amount_received": amount})
+}
+func (slf *ServiceContractSearch) AmountInvoicedAdd(tx *gorm.DB, id int, amount decimal.Decimal) error {
+	slf.Orm = tx
+	record, err := slf.SetId(id).First()
+	if err != nil {
+		return err
+	}
+	amount = record.AmountInvoiced.Add(amount)
+	return slf.UpdateByMap(map[string]interface{}{"amount_invoiced": amount})
+}
+func (slf *ServiceContractSearch) AmountNotInvoicedAdd(tx *gorm.DB, id int, amount decimal.Decimal) error {
+	slf.Orm = tx
+	record, err := slf.SetId(id).First()
+	if err != nil {
+		return err
+	}
+	amount = record.AmountUnInvoiced.Add(amount)
+	return slf.UpdateByMap(map[string]interface{}{"amount_not_invoiced": amount})
+}
diff --git a/model/serviceOrderStatus.go b/model/serviceOrderStatus.go
index b4b4046..4697fe2 100644
--- a/model/serviceOrderStatus.go
+++ b/model/serviceOrderStatus.go
@@ -12,18 +12,18 @@
 	// ServiceOrderStatus 鏈嶅姟鍗曠姸鎬�
 	ServiceOrderStatus struct {
 		Id   int    `json:"id" gorm:"column:id;type:int;primary_key;AUTO_INCREMENT"`
-	    Name string `json:"name" gorm:"column:name;type:varchar(255);not null;default:'';comment:鍚嶇О"`
+		Name string `json:"name" gorm:"column:name;type:varchar(255);not null;default:'';comment:鍚嶇О"`
 	}
 
 	// ServiceOrderStatusSearch 鏈嶅姟鍗曠姸鎬佹悳绱㈡潯浠�
 	ServiceOrderStatusSearch struct {
 		ServiceOrderStatus
-		Orm *gorm.DB
-        QueryClass  constvar.ServiceOrderStatusQueryClass
-        KeywordType constvar.ServiceOrderStatusKeywordType
-        Keyword     string
-        PageNum  int
-        PageSize int
+		Orm         *gorm.DB
+		QueryClass  constvar.ServiceOrderStatusQueryClass
+		KeywordType constvar.ServiceOrderStatusKeywordType
+		Keyword     string
+		PageNum     int
+		PageSize    int
 	}
 )
 
diff --git a/pkg/ecode/code.go b/pkg/ecode/code.go
index 9701a5a..efc2052 100644
--- a/pkg/ecode/code.go
+++ b/pkg/ecode/code.go
@@ -214,12 +214,14 @@
 	SalesReturnUpdateErr = 2900005 // 鏇存柊閿�鍞��璐у崟澶辫触
 	SalesReturnDeleteErr = 2900006 // 鍒犻櫎閿�鍞��璐у崟澶辫触
 
-	SalesRefundExist     = 3000001 // 閿�鍞��娆惧崟宸插瓨鍦�
-	SalesRefundNotExist  = 3000002 // 閿�鍞��娆惧崟涓嶅瓨鍦�
-	SalesRefundListErr   = 3000003 // 鑾峰彇閿�鍞��娆惧崟鍒楄〃澶辫触
-	SalesRefundSetErr    = 3000004 // 璁剧疆閿�鍞��娆惧崟澶辫触
-	SalesRefundUpdateErr = 3000005 // 鏇存柊閿�鍞��娆惧崟澶辫触
-	SalesRefundDeleteErr = 3000006 // 鍒犻櫎閿�鍞��娆惧崟澶辫触
+	SalesRefundExist                   = 3000001 // 閿�鍞��娆惧崟宸插瓨鍦�
+	SalesRefundNotExist                = 3000002 // 閿�鍞��娆惧崟涓嶅瓨鍦�
+	SalesRefundListErr                 = 3000003 // 鑾峰彇閿�鍞��娆惧崟鍒楄〃澶辫触
+	SalesRefundSetErr                  = 3000004 // 璁剧疆閿�鍞��娆惧崟澶辫触
+	SalesRefundUpdateErr               = 3000005 // 鏇存柊閿�鍞��娆惧崟澶辫触
+	SalesRefundDeleteErr               = 3000006 // 鍒犻櫎閿�鍞��娆惧崟澶辫触
+	SalesRefundProductNotExist         = 3000007 // 閫�璐т骇鍝佷笉瀛樺湪
+	SalesRefundProductPriceOrAmountErr = 3000009 // 閫�璐т骇鍝佷环鏍兼垨鏁伴噺閿欒
 
 	ContractExist     = 3100001 // 鍚堝悓宸插瓨鍦�
 	ContractNotExist  = 3100002 // 鍚堝悓涓嶅瓨鍦�
diff --git a/pkg/ecode/msg.go b/pkg/ecode/msg.go
index deeff57..f0df18e 100644
--- a/pkg/ecode/msg.go
+++ b/pkg/ecode/msg.go
@@ -23,6 +23,8 @@
 	SContractProductPriceLowerThanInvoiceAmountErr:             "浜у搧鎬讳环浣庝簬宸插紑绁ㄩ噾棰�",
 	SContractProductPriceLowerThanReceivedAmountErr:            "浜у搧鎬讳环浣庝簬宸叉敹閲戦",
 	SContractInvoiceProductPriceGreaterThanReceivableAmountErr: "寮�绁ㄦ�婚楂樹簬搴旀敹閲戦",
+	SalesRefundProductNotExist:                                 "閫�璐т骇鍝佷笉瀛樺湪",
+	SalesRefundProductPriceOrAmountErr:                         "閫�璐т骇鍝佷环鏍兼垨鏁伴噺閿欒",
 }
 
 func GetMsg(errCode int) (errMsg string) {
diff --git a/service/invoice.go b/service/invoice.go
index 59301a9..996d184 100644
--- a/service/invoice.go
+++ b/service/invoice.go
@@ -17,27 +17,53 @@
 
 func (InvoiceService) AddInvoice(invoice *model.Invoice) int {
 
-	if invoice.SourceType == constvar.InvoiceSourceTypeServiceContract {
+	if invoice.SourceType == constvar.InvoiceSourceTypeServiceContract { //鏇存柊鏈嶅姟鍚堝悓宸插紑绁ㄩ噾棰�
 		serviceContract, err := model.NewServiceContractSearch().SetId(invoice.SourceId).SetPreload(true).First()
 		if err != nil {
 			return ecode.DBErr
 		}
-		var amountInvoiced decimal.Decimal
+		var amountInvoiced, amountNotInvoiced decimal.Decimal
 		rightProducts := NewProductsService().PickRightProducts(invoice.Products, serviceContract.Products)
 		for _, product := range rightProducts {
 			amountInvoiced = serviceContract.AmountInvoiced.Add(product.Amount.Mul(product.Price))
+			amountNotInvoiced = serviceContract.AmountUnInvoiced.Sub(product.Amount.Mul(product.Price))
 		}
 		amountInvoiced = amountInvoiced.Round(2)
-		if amountInvoiced.GreaterThan(serviceContract.AmountReceivable) {
-			return ecode.SContractInvoiceProductPriceGreaterThanReceivableAmountErr
-		}
+		amountNotInvoiced = amountNotInvoiced.Round(2)
 		err = model.WithTransaction(func(db *gorm.DB) error {
 			err = model.NewInvoiceSearch().Create(invoice)
 			if err != nil {
 				return err
 			}
 			return model.NewServiceContractSearch().SetId(invoice.SourceId).UpdateByMap(map[string]interface{}{
-				"amount_invoiced": amountInvoiced,
+				"amount_invoiced":     amountInvoiced,
+				"amount_not_invoiced": amountNotInvoiced,
+			})
+		})
+		if err != nil {
+			return ecode.DBErr
+		}
+	} else if invoice.SourceType == constvar.InvoiceSourceTypeServiceContract { //鏇存柊閿�鍞槑缁嗗凡寮�绁ㄩ噾棰�
+		salesDetails, err := model.NewSalesDetailsSearch().SetId(invoice.SourceId).SetPreload(true).First()
+		if err != nil {
+			return ecode.DBErr
+		}
+		var amountInvoiced, amountNotInvoiced decimal.Decimal
+		rightProducts := NewProductsService().PickRightProducts(invoice.Products, salesDetails.Products)
+		for _, product := range rightProducts {
+			amountInvoiced = salesDetails.AmountInvoiced.Add(product.Amount.Mul(product.Price))
+			amountNotInvoiced = salesDetails.AmountUnInvoiced.Sub(product.Amount.Mul(product.Price))
+		}
+		amountInvoiced = amountInvoiced.Round(2)
+		amountNotInvoiced = amountNotInvoiced.Round(2)
+		err = model.WithTransaction(func(db *gorm.DB) error {
+			err = model.NewInvoiceSearch().Create(invoice)
+			if err != nil {
+				return err
+			}
+			return model.NewSalesDetailsSearch().SetId(invoice.SourceId).UpdateByMap(map[string]interface{}{
+				"amount_invoiced":     amountInvoiced,
+				"amount_not_invoiced": amountNotInvoiced,
 			})
 		})
 		if err != nil {
@@ -49,7 +75,64 @@
 }
 
 func (InvoiceService) DeleteInvoice(id int) int {
-	err := model.NewInvoiceSearch().SetId(id).Delete()
+	invoice, err := model.NewInvoiceSearch().SetId(id).First()
+	if err != nil {
+		return ecode.DBErr
+	}
+	if invoice.SourceType == constvar.InvoiceSourceTypeServiceContract { //鏇存柊鏈嶅姟鍚堝悓宸插紑绁ㄩ噾棰�
+		serviceContract, err := model.NewServiceContractSearch().SetId(invoice.SourceId).SetPreload(true).First()
+		if err != nil {
+			return ecode.DBErr
+		}
+		var amountInvoiced, amountNotInvoiced decimal.Decimal
+		rightProducts := NewProductsService().PickRightProducts(invoice.Products, serviceContract.Products)
+		for _, product := range rightProducts {
+			amountInvoiced = serviceContract.AmountInvoiced.Sub(product.Amount.Mul(product.Price))
+			amountNotInvoiced = serviceContract.AmountUnInvoiced.Add(product.Amount.Mul(product.Price))
+		}
+		amountInvoiced = amountInvoiced.Round(2)
+		amountNotInvoiced = amountNotInvoiced.Round(2)
+		err = model.WithTransaction(func(db *gorm.DB) error {
+			err := model.NewInvoiceSearch().SetId(id).Delete()
+			if err != nil {
+				return err
+			}
+			return model.NewServiceContractSearch().SetId(invoice.SourceId).UpdateByMap(map[string]interface{}{
+				"amount_invoiced":     amountInvoiced,
+				"amount_not_invoiced": amountNotInvoiced,
+			})
+		})
+		if err != nil {
+			return ecode.DBErr
+		}
+	} else if invoice.SourceType == constvar.InvoiceSourceTypeServiceContract { //鏇存柊閿�鍞槑缁嗗凡寮�绁ㄩ噾棰�
+		salesDetails, err := model.NewSalesDetailsSearch().SetId(invoice.SourceId).SetPreload(true).First()
+		if err != nil {
+			return ecode.DBErr
+		}
+		var amountInvoiced, amountNotInvoiced decimal.Decimal
+		rightProducts := NewProductsService().PickRightProducts(invoice.Products, salesDetails.Products)
+		for _, product := range rightProducts {
+			amountInvoiced = salesDetails.AmountInvoiced.Sub(product.Amount.Mul(product.Price))
+			amountNotInvoiced = salesDetails.AmountUnInvoiced.Add(product.Amount.Mul(product.Price))
+		}
+		amountInvoiced = amountInvoiced.Round(2)
+		amountNotInvoiced = amountNotInvoiced.Round(2)
+		err = model.WithTransaction(func(db *gorm.DB) error {
+			err := model.NewInvoiceSearch().SetId(id).Delete()
+			if err != nil {
+				return err
+			}
+			return model.NewSalesDetailsSearch().SetId(invoice.SourceId).UpdateByMap(map[string]interface{}{
+				"amount_invoiced":     amountInvoiced,
+				"amount_not_invoiced": amountNotInvoiced,
+			})
+		})
+		if err != nil {
+			return ecode.DBErr
+		}
+	}
+
 	if err != nil {
 		return ecode.DBErr
 	}
@@ -88,20 +171,20 @@
 		if err != nil {
 			return ecode.DBErr
 		}
-		var amountInvoiced decimal.Decimal
+		var amountInvoiced, amountNotInvoiced decimal.Decimal
 		newProducts, removedProducts := NewProductsService().PickDiffProducts(invoice.Products, serviceContract.Products)
 		for _, product := range newProducts {
 			amountInvoiced = serviceContract.AmountInvoiced.Add(product.Amount.Mul(product.Price))
+			amountNotInvoiced = serviceContract.AmountUnInvoiced.Sub(product.Amount.Mul(product.Price))
 		}
 		removedProductIds := make([]uint, 0, len(removedProducts))
 		for _, product := range removedProducts {
 			amountInvoiced = serviceContract.AmountInvoiced.Sub(product.Amount.Mul(product.Price))
+			amountNotInvoiced = serviceContract.AmountUnInvoiced.Add(product.Amount.Mul(product.Price))
 			removedProductIds = append(removedProductIds, product.Id)
 		}
 		amountInvoiced = amountInvoiced.Round(2)
-		if amountInvoiced.GreaterThan(serviceContract.AmountReceivable) {
-			return ecode.SContractInvoiceProductPriceGreaterThanReceivableAmountErr
-		}
+		amountNotInvoiced = amountNotInvoiced.Round(2)
 		err = model.WithTransaction(func(db *gorm.DB) error {
 			err = model.NewInvoiceSearch().SetId(invoice.Id).Save(invoice)
 			if err != nil {
@@ -114,7 +197,45 @@
 				}
 			}
 			return model.NewServiceContractSearch().SetId(invoice.SourceId).UpdateByMap(map[string]interface{}{
-				"amount_invoiced": amountInvoiced,
+				"amount_invoiced":     amountInvoiced,
+				"amount_not_invoiced": amountNotInvoiced,
+			})
+		})
+		if err != nil {
+			return ecode.DBErr
+		}
+	} else if invoice.SourceType == constvar.InvoiceSourceTypeServiceContract { //鏇存柊閿�鍞槑缁嗗凡寮�绁ㄩ噾棰�
+		salesDetails, err := model.NewSalesDetailsSearch().SetId(invoice.SourceId).SetPreload(true).First()
+		if err != nil {
+			return ecode.DBErr
+		}
+		var amountInvoiced, amountNotInvoiced decimal.Decimal
+		newProducts, removedProducts := NewProductsService().PickDiffProducts(invoice.Products, salesDetails.Products)
+		for _, product := range newProducts {
+			amountInvoiced = salesDetails.AmountInvoiced.Add(product.Amount.Mul(product.Price))
+			amountNotInvoiced = salesDetails.AmountUnInvoiced.Sub(product.Amount.Mul(product.Price))
+		}
+		removedProductIds := make([]uint, 0, len(removedProducts))
+		for _, product := range removedProducts {
+			amountInvoiced = salesDetails.AmountInvoiced.Sub(product.Amount.Mul(product.Price))
+			amountNotInvoiced = salesDetails.AmountUnInvoiced.Add(product.Amount.Mul(product.Price))
+			removedProductIds = append(removedProductIds, product.Id)
+		}
+		amountInvoiced = amountInvoiced.Round(2)
+		err = model.WithTransaction(func(db *gorm.DB) error {
+			err = model.NewInvoiceSearch().SetId(invoice.Id).Save(invoice)
+			if err != nil {
+				return err
+			}
+			if len(removedProductIds) > 0 {
+				err = model.NewInvoiceProductSearch().SetInvoiceId(invoice.Id).SetProductIds(removedProductIds).Delete()
+				if err != nil {
+					return err
+				}
+			}
+			return model.NewSalesDetailsSearch().SetId(invoice.SourceId).UpdateByMap(map[string]interface{}{
+				"amount_invoiced":     amountInvoiced,
+				"amount_not_invoiced": amountNotInvoiced,
 			})
 		})
 		if err != nil {
diff --git a/service/receipt.go b/service/receipt.go
index 834c6df..9c49878 100644
--- a/service/receipt.go
+++ b/service/receipt.go
@@ -1,9 +1,12 @@
 package service
 
 import (
+	"aps_crm/constvar"
 	"aps_crm/model"
 	"aps_crm/model/request"
 	"aps_crm/pkg/ecode"
+	"github.com/shopspring/decimal"
+	"gorm.io/gorm"
 )
 
 type ReceiptService struct{}
@@ -13,16 +16,108 @@
 }
 
 func (ReceiptService) AddReceipt(receipt *model.Receipt) int {
-	err := model.NewReceiptSearch().Create(receipt)
+	var moneyAdder model.MoneyAdder
+	var sourceId int
+	var collection *model.ServiceCollectionPlan
+	var err error
+	switch receipt.SourceType {
+	case constvar.ReceiptSourceTypeSalesDetails:
+		moneyAdder = model.NewSalesDetailsSearch()
+		sourceId = receipt.SourceId
+	case constvar.ReceiptSourceTypeServiceContract:
+		moneyAdder = model.NewServiceContractSearch()
+		sourceId = receipt.SourceId
+	case constvar.ReceiptSourceTypeCollectionPlan:
+		collection, err = model.NewServiceCollectionPlanSearch().SetId(receipt.SourceId).First()
+		if err != nil {
+			return ecode.DBErr
+		}
+		sourceId = collection.SourceId
+		switch collection.SourceType {
+		case constvar.CollectionSourceTypeSaleDetails:
+			moneyAdder = model.NewSalesDetailsSearch()
+		case constvar.CollectionSourceTypeServiceContract:
+			moneyAdder = model.NewServiceContractSearch()
+		}
+	}
+	err = model.WithTransaction(func(db *gorm.DB) error {
+		err := model.NewReceiptSearch().SetOrm(db).Create(receipt)
+		if err != nil {
+			return err
+		}
+		if receipt.SourceType == constvar.ReceiptSourceTypeCollectionPlan {
+			err = model.NewServiceCollectionPlanSearch().SetOrm(db).UpdateStatusAndAmount(collection, receipt.Amount)
+			if err != nil {
+				return err
+			}
+		}
+		err = moneyAdder.AmountReceivableAdd(db, sourceId, decimal.Zero.Sub(receipt.Amount).Round(2))
+		if err != nil {
+			return err
+		}
+		err = moneyAdder.AmountReceivedAdd(db, sourceId, receipt.Amount.Round(2))
+		if err != nil {
+			return err
+		}
+		return nil
+	})
 	if err != nil {
 		return ecode.DBErr
 	}
-
 	return ecode.OK
 }
 
 func (ReceiptService) DeleteReceipt(id int) int {
-	err := model.NewReceiptSearch().SetId(id).Delete()
+	receipt, err := model.NewReceiptSearch().SetId(id).First()
+	if err != nil {
+		return ecode.DBErr
+	}
+	var moneyAdder model.MoneyAdder
+	var sourceId int
+	var collection *model.ServiceCollectionPlan
+	switch receipt.SourceType {
+	case constvar.ReceiptSourceTypeSalesDetails:
+		moneyAdder = model.NewSalesDetailsSearch()
+		sourceId = receipt.SourceId
+	case constvar.ReceiptSourceTypeServiceContract:
+		moneyAdder = model.NewServiceContractSearch()
+		sourceId = receipt.SourceId
+	case constvar.ReceiptSourceTypeCollectionPlan:
+		collection, err = model.NewServiceCollectionPlanSearch().SetId(receipt.SourceId).First()
+		if err != nil {
+			return ecode.DBErr
+		}
+		sourceId = collection.SourceId
+		switch collection.SourceType {
+		case constvar.CollectionSourceTypeSaleDetails:
+			moneyAdder = model.NewSalesDetailsSearch()
+		case constvar.CollectionSourceTypeServiceContract:
+			moneyAdder = model.NewServiceContractSearch()
+		}
+	}
+	err = model.WithTransaction(func(db *gorm.DB) error {
+		err := model.NewReceiptSearch().SetOrm(db).SetId(id).Delete()
+		if err != nil {
+			return err
+		}
+
+		if receipt.SourceType == constvar.ReceiptSourceTypeCollectionPlan {
+			err = model.NewServiceCollectionPlanSearch().SetOrm(db).UpdateStatusAndAmount(collection, decimal.Zero.Sub(receipt.Amount))
+			if err != nil {
+				return err
+			}
+		}
+
+		err = moneyAdder.AmountReceivableAdd(db, sourceId, receipt.Amount.Round(2))
+		if err != nil {
+			return err
+		}
+		err = moneyAdder.AmountReceivedAdd(db, sourceId, decimal.Zero.Sub(receipt.Amount).Round(2))
+		if err != nil {
+			return err
+		}
+		return nil
+	})
 	if err != nil {
 		return ecode.DBErr
 	}
@@ -46,9 +141,7 @@
 			return ecode.DBErr
 		}
 
-		err = model.NewReceiptSearch().SetId(v.Id).Updates(map[string]interface{}{
-
-		})
+		err = model.NewReceiptSearch().SetId(v.Id).Updates(map[string]interface{}{})
 		if err != nil {
 			return ecode.DBErr
 		}
@@ -58,9 +151,57 @@
 }
 
 func (ReceiptService) UpdateReceipt(receipt *model.Receipt) int {
-		err := model.NewReceiptSearch().SetId(receipt.Id).Save(receipt)
+	old, err := model.NewReceiptSearch().SetId(receipt.Id).First()
+	if err != nil {
+		return ecode.DBErr
+	}
+	var moneyAdder model.MoneyAdder
+	var sourceId int
+	var collection *model.ServiceCollectionPlan
+	switch receipt.SourceType {
+	case constvar.ReceiptSourceTypeSalesDetails:
+		moneyAdder = model.NewSalesDetailsSearch()
+		sourceId = receipt.SourceId
+	case constvar.ReceiptSourceTypeServiceContract:
+		moneyAdder = model.NewServiceContractSearch()
+		sourceId = receipt.SourceId
+	case constvar.ReceiptSourceTypeCollectionPlan:
+		collection, err = model.NewServiceCollectionPlanSearch().SetId(receipt.SourceId).First()
 		if err != nil {
 			return ecode.DBErr
 		}
+		sourceId = collection.SourceId
+		switch collection.SourceType {
+		case constvar.CollectionSourceTypeSaleDetails:
+			moneyAdder = model.NewSalesDetailsSearch()
+		case constvar.CollectionSourceTypeServiceContract:
+			moneyAdder = model.NewServiceContractSearch()
+		}
+	}
+	err = model.WithTransaction(func(db *gorm.DB) error {
+		err = model.NewReceiptSearch().SetId(receipt.Id).Save(receipt)
+		if err != nil {
+			return err
+		}
+		diffAmount := receipt.Amount.Sub(old.Amount)
+		if receipt.SourceType == constvar.ReceiptSourceTypeCollectionPlan {
+			err = model.NewServiceCollectionPlanSearch().SetOrm(db).UpdateStatusAndAmount(collection, diffAmount)
+			if err != nil {
+				return err
+			}
+		}
+		err = moneyAdder.AmountReceivedAdd(db, sourceId, diffAmount.Round(2))
+		if err != nil {
+			return err
+		}
+		err = moneyAdder.AmountReceivableAdd(db, sourceId, decimal.Zero.Sub(diffAmount).Round(2))
+		if err != nil {
+			return err
+		}
+		return nil
+	})
+	if err != nil {
+		return ecode.DBErr
+	}
 	return ecode.OK
 }
diff --git a/service/salesDetails.go b/service/salesDetails.go
index d504748..81e10b2 100644
--- a/service/salesDetails.go
+++ b/service/salesDetails.go
@@ -4,11 +4,23 @@
 	"aps_crm/constvar"
 	"aps_crm/model"
 	"aps_crm/pkg/ecode"
+	"github.com/shopspring/decimal"
 )
 
 type SalesDetailsService struct{}
 
 func (SalesDetailsService) AddSalesDetails(salesDetails *model.SalesDetails) int {
+	salesDetails.AmountReceivable = decimal.Zero.Round(2)
+	salesDetails.AmountInvoiced = decimal.Zero.Round(2)
+	salesDetails.AmountReceived = decimal.Zero.Round(2)
+	salesDetails.AmountUnInvoiced = decimal.Zero.Round(2)
+	salesDetails.AmountTotal = decimal.Zero.Round(2)
+	for _, product := range salesDetails.Products {
+		salesDetails.AmountTotal = salesDetails.AmountTotal.Add(product.Amount.Mul(product.Price))
+	}
+	salesDetails.AmountTotal = salesDetails.AmountTotal.Round(2)
+	salesDetails.AmountReceivable = salesDetails.AmountTotal
+	salesDetails.AmountUnInvoiced = salesDetails.AmountTotal
 	err := model.NewSalesDetailsSearch().Create(salesDetails)
 	if err != nil {
 		return ecode.SalesDetailsExist
@@ -18,7 +30,7 @@
 }
 
 func (SalesDetailsService) DeleteSalesDetails(id int) int {
-	_, err := model.NewSalesDetailsSearch().SetId(id).Find()
+	_, err := model.NewSalesDetailsSearch().SetId(id).First()
 	if err != nil {
 		return ecode.SalesDetailsNotExist
 	}
@@ -32,10 +44,24 @@
 
 func (SalesDetailsService) UpdateSalesDetails(salesDetails *model.SalesDetails) int {
 	// check salesDetails exist
-	_, err := model.NewSalesDetailsSearch().SetId(salesDetails.Id).Find()
+	old, err := model.NewSalesDetailsSearch().SetId(salesDetails.Id).First()
 	if err != nil {
 		return ecode.SalesDetailsNotExist
 	}
+	var totalAmount decimal.Decimal
+	totalAmount = salesDetails.AmountTotal
+	newProducts, removedProducts := NewProductsService().PickDiffProducts(salesDetails.Products, old.Products)
+	for _, product := range newProducts {
+		totalAmount = totalAmount.Add(product.Amount.Mul(product.Price))
+	}
+	removedProductIds := make([]uint, 0, len(removedProducts))
+	for _, product := range removedProducts {
+		totalAmount = totalAmount.Sub(product.Amount.Mul(product.Price))
+		removedProductIds = append(removedProductIds, product.Id)
+	}
+	salesDetails.AmountTotal = totalAmount.Round(2)
+	salesDetails.AmountReceivable = salesDetails.AmountTotal.Sub(salesDetails.AmountReceived)
+	salesDetails.AmountUnInvoiced = salesDetails.AmountTotal.Sub(salesDetails.AmountInvoiced)
 
 	err = model.NewSalesDetailsSearch().SetId(salesDetails.Id).Update(salesDetails)
 	if err != nil {
diff --git a/service/salesRefund.go b/service/salesRefund.go
index de91872..1403dac 100644
--- a/service/salesRefund.go
+++ b/service/salesRefund.go
@@ -1,6 +1,7 @@
 package service
 
 import (
+	"aps_crm/constvar"
 	"aps_crm/model"
 	"aps_crm/pkg/ecode"
 )
@@ -8,11 +9,36 @@
 type SalesRefundService struct{}
 
 func (SalesRefundService) AddSalesRefund(salesRefund *model.SalesRefund) int {
-	err := model.NewSalesRefundSearch().Create(salesRefund)
+	salesReturnRecord, err := model.NewSalesReturnSearch().SetId(salesRefund.SourceId).Find()
+	if err != nil {
+		return ecode.SalesReturnNotExist
+	}
+
+	if code := CheckProduct(salesReturnRecord.Products, salesRefund.Products); code != ecode.OK {
+		return code
+	}
+
+	err = model.NewSalesRefundSearch().Create(salesRefund)
 	if err != nil {
 		return ecode.SalesRefundExist
 	}
 
+	return ecode.OK
+}
+
+func CheckProduct(returnProducts, refundProducts []*model.Product) int {
+	returnProductsMap := make(map[uint]*model.Product, len(returnProducts))
+	for _, product := range returnProducts {
+		returnProductsMap[product.Id] = product
+	}
+	for _, product := range refundProducts {
+		if returnProductsMap[product.Id] == nil {
+			return ecode.SalesRefundProductNotExist
+		}
+		if returnProductsMap[product.Id].Price != product.Price || product.Amount.GreaterThan(returnProductsMap[product.Id].Amount) {
+			return ecode.SalesRefundProductPriceOrAmountErr
+		}
+	}
 	return ecode.OK
 }
 
@@ -36,6 +62,15 @@
 		return ecode.SalesRefundNotExist
 	}
 
+	salesReturnRecord, err := model.NewSalesReturnSearch().SetId(salesRefund.SourceId).Find()
+	if err != nil {
+		return ecode.SalesReturnNotExist
+	}
+
+	if code := CheckProduct(salesReturnRecord.Products, salesRefund.Products); code != ecode.OK {
+		return code
+	}
+
 	err = model.NewSalesRefundSearch().SetId(salesRefund.Id).Update(salesRefund)
 	if err != nil {
 		return ecode.SalesRefundSetErr
@@ -44,9 +79,13 @@
 	return ecode.OK
 }
 
-func (SalesRefundService) GetSalesRefundList(page, pageSize int, keyword string) ([]*model.SalesRefund, int64, int) {
+func (SalesRefundService) GetSalesRefundList(page, pageSize int, keywordType constvar.SalesRefundKeywordType, keyword string) ([]*model.SalesRefund, int64, int) {
 	// get contact list
-	contacts, total, err := model.NewSalesRefundSearch().SetKeyword(keyword).SetPage(page, pageSize).FindAll()
+	contacts, total, err := model.NewSalesRefundSearch().
+		SetKeywordType(keywordType).
+		SetKeyword(keyword).
+		SetPreload(true).
+		SetPage(page, pageSize).FindAll()
 	if err != nil {
 		return nil, 0, ecode.SalesRefundListErr
 	}
diff --git a/service/salesReturn.go b/service/salesReturn.go
index 655e2f8..6a4bab0 100644
--- a/service/salesReturn.go
+++ b/service/salesReturn.go
@@ -7,7 +7,7 @@
 
 type SalesReturnService struct{}
 
-func (SalesReturnService) AddSalesReturn(salesReturn *model.SalesReturn) int {
+func (slf SalesReturnService) AddSalesReturn(salesReturn *model.SalesReturn) int {
 	err := model.NewSalesReturnSearch().Create(salesReturn)
 	if err != nil {
 		return ecode.SalesReturnExist
diff --git a/service/serviceContract.go b/service/serviceContract.go
index eb901f2..6da4367 100644
--- a/service/serviceContract.go
+++ b/service/serviceContract.go
@@ -13,10 +13,15 @@
 	serviceContract.AmountReceivable = decimal.Zero.Round(2)
 	serviceContract.AmountInvoiced = decimal.Zero.Round(2)
 	serviceContract.AmountReceived = decimal.Zero.Round(2)
+	serviceContract.AmountUnInvoiced = decimal.Zero.Round(2)
+	serviceContract.AmountTotal = decimal.Zero.Round(2)
 	for _, product := range serviceContract.Products {
-		serviceContract.AmountReceivable = serviceContract.AmountReceivable.Add(product.Amount.Mul(product.Price))
+		serviceContract.AmountTotal = serviceContract.AmountTotal.Add(product.Amount.Mul(product.Price))
 	}
-	serviceContract.AmountReceivable = serviceContract.AmountReceivable.Round(2)
+	serviceContract.AmountTotal = serviceContract.AmountTotal.Round(2)
+	serviceContract.AmountReceivable = serviceContract.AmountTotal
+	serviceContract.AmountUnInvoiced = serviceContract.AmountTotal
+
 	err := model.NewServiceContractSearch().Create(serviceContract)
 	if err != nil {
 		return ecode.SContractExist
@@ -31,19 +36,21 @@
 	if err != nil {
 		return ecode.SContractNotExist
 	}
-	var amountReceivable decimal.Decimal
-	for _, product := range serviceContract.Products {
-		amountReceivable = serviceContract.AmountReceivable.Add(product.Amount.Mul(product.Price))
+	var totalAmount decimal.Decimal
+	totalAmount = serviceContract.AmountTotal
+	newProducts, removedProducts := NewProductsService().PickDiffProducts(serviceContract.Products, old.Products)
+	for _, product := range newProducts {
+		totalAmount = totalAmount.Add(product.Amount.Mul(product.Price))
 	}
-	if amountReceivable.LessThan(serviceContract.AmountInvoiced) {
-		return ecode.SContractProductPriceLowerThanInvoiceAmountErr
+	removedProductIds := make([]uint, 0, len(removedProducts))
+	for _, product := range removedProducts {
+		totalAmount = totalAmount.Sub(product.Amount.Mul(product.Price))
+		removedProductIds = append(removedProductIds, product.Id)
 	}
-	if amountReceivable.LessThan(serviceContract.AmountReceived) {
-		return ecode.SContractProductPriceLowerThanReceivedAmountErr
-	}
-	serviceContract.AmountInvoiced = old.AmountReceived
-	serviceContract.AmountReceived = old.AmountReceived
-	serviceContract.AmountReceivable = amountReceivable.Round(2)
+	serviceContract.AmountTotal = totalAmount.Round(2)
+	serviceContract.AmountReceivable = serviceContract.AmountTotal.Sub(serviceContract.AmountReceived)
+	serviceContract.AmountUnInvoiced = serviceContract.AmountTotal.Sub(serviceContract.AmountInvoiced)
+
 	err = model.NewServiceContractSearch().SetId(serviceContract.Id).Update(serviceContract)
 	if err != nil {
 		return ecode.SContractSetErr

--
Gitblit v1.8.0