Add responsible signature to aftersales confirmation
This commit is contained in:
@@ -272,6 +272,7 @@ type AftersalesOrder struct {
|
|||||||
ConfirmedAt *time.Time `json:"confirmedAt"`
|
ConfirmedAt *time.Time `json:"confirmedAt"`
|
||||||
RejectCount int `gorm:"default:0" json:"rejectCount"`
|
RejectCount int `gorm:"default:0" json:"rejectCount"`
|
||||||
Signature string `gorm:"type:text" json:"signature,omitempty"`
|
Signature string `gorm:"type:text" json:"signature,omitempty"`
|
||||||
|
ResponsibleSignature string `gorm:"type:text" json:"responsibleSignature,omitempty"`
|
||||||
|
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
UpdatedAt time.Time `json:"updatedAt"`
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
@@ -310,10 +311,12 @@ type SubmitForConfirmationDTO struct {
|
|||||||
|
|
||||||
// CustomerConfirmDTO 客户确认请求
|
// CustomerConfirmDTO 客户确认请求
|
||||||
// Signature 为客户在网页上手写签名的 base64 PNG dataURL,仅 authorize 时必填
|
// Signature 为客户在网页上手写签名的 base64 PNG dataURL,仅 authorize 时必填
|
||||||
|
// ResponsibleSignature 为负责人在网页上手写签名的 base64 PNG dataURL,仅 authorize 时必填
|
||||||
// RejectReason 为客户拒绝的原因,仅 reject 时必填
|
// RejectReason 为客户拒绝的原因,仅 reject 时必填
|
||||||
type CustomerConfirmDTO struct {
|
type CustomerConfirmDTO struct {
|
||||||
Action string `json:"action" validate:"required,oneof=authorize reject"`
|
Action string `json:"action" validate:"required,oneof=authorize reject"`
|
||||||
Signature string `json:"signature,omitempty" validate:"required_if=Action authorize"`
|
Signature string `json:"signature,omitempty" validate:"required_if=Action authorize"`
|
||||||
|
ResponsibleSignature string `json:"responsibleSignature,omitempty" validate:"required_if=Action authorize"`
|
||||||
RejectReason string `json:"rejectReason,omitempty" validate:"required_if=Action reject"`
|
RejectReason string `json:"rejectReason,omitempty" validate:"required_if=Action reject"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,4 +340,5 @@ type AftersalesPublicView struct {
|
|||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
ConfirmedAt *time.Time `json:"confirmedAt"`
|
ConfirmedAt *time.Time `json:"confirmedAt"`
|
||||||
Signature string `json:"signature,omitempty"`
|
Signature string `json:"signature,omitempty"`
|
||||||
|
ResponsibleSignature string `json:"responsibleSignature,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -341,6 +341,7 @@ func (s *AftersalesService) PublicQuery(serialNumber string) (*models.Aftersales
|
|||||||
CreatedAt: order.CreatedAt,
|
CreatedAt: order.CreatedAt,
|
||||||
ConfirmedAt: order.ConfirmedAt,
|
ConfirmedAt: order.ConfirmedAt,
|
||||||
Signature: order.Signature,
|
Signature: order.Signature,
|
||||||
|
ResponsibleSignature: order.ResponsibleSignature,
|
||||||
}
|
}
|
||||||
if order.Technician != nil {
|
if order.Technician != nil {
|
||||||
view.TechnicianName = order.Technician.Name
|
view.TechnicianName = order.Technician.Name
|
||||||
@@ -372,10 +373,14 @@ func (s *AftersalesService) CustomerConfirm(serialNumber string, dto models.Cust
|
|||||||
if err := validateSignature(dto.Signature); err != nil {
|
if err := validateSignature(dto.Signature); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if err := validateSignature(dto.ResponsibleSignature); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
order.WorkOrderStatus = WorkOrderStatusClosed
|
order.WorkOrderStatus = WorkOrderStatusClosed
|
||||||
order.AuthorizationStatus = AuthorizationStatusAuthorized
|
order.AuthorizationStatus = AuthorizationStatusAuthorized
|
||||||
order.ConfirmedAt = &now
|
order.ConfirmedAt = &now
|
||||||
order.Signature = strings.TrimSpace(dto.Signature)
|
order.Signature = strings.TrimSpace(dto.Signature)
|
||||||
|
order.ResponsibleSignature = strings.TrimSpace(dto.ResponsibleSignature)
|
||||||
case "reject":
|
case "reject":
|
||||||
reason := strings.TrimSpace(dto.RejectReason)
|
reason := strings.TrimSpace(dto.RejectReason)
|
||||||
if reason == "" {
|
if reason == "" {
|
||||||
|
|||||||
@@ -214,9 +214,11 @@ func TestAftersalesService_CustomerConfirm_Authorize(t *testing.T) {
|
|||||||
}, owner)
|
}, owner)
|
||||||
|
|
||||||
sig := validSignatureFixture()
|
sig := validSignatureFixture()
|
||||||
|
responsibleSig := validSignatureFixture()
|
||||||
view, err := svc.CustomerConfirm(order.SerialNumber, models.CustomerConfirmDTO{
|
view, err := svc.CustomerConfirm(order.SerialNumber, models.CustomerConfirmDTO{
|
||||||
Action: "authorize",
|
Action: "authorize",
|
||||||
Signature: sig,
|
Signature: sig,
|
||||||
|
ResponsibleSignature: responsibleSig,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, view)
|
assert.NotNil(t, view)
|
||||||
@@ -224,10 +226,12 @@ func TestAftersalesService_CustomerConfirm_Authorize(t *testing.T) {
|
|||||||
assert.Equal(t, AuthorizationStatusAuthorized, view.AuthorizationStatus)
|
assert.Equal(t, AuthorizationStatusAuthorized, view.AuthorizationStatus)
|
||||||
assert.NotNil(t, view.ConfirmedAt)
|
assert.NotNil(t, view.ConfirmedAt)
|
||||||
assert.Equal(t, sig, view.Signature)
|
assert.Equal(t, sig, view.Signature)
|
||||||
|
assert.Equal(t, responsibleSig, view.ResponsibleSignature)
|
||||||
|
|
||||||
var refreshed models.AftersalesOrder
|
var refreshed models.AftersalesOrder
|
||||||
database.DB.Where("serial_number = ?", order.SerialNumber).First(&refreshed)
|
database.DB.Where("serial_number = ?", order.SerialNumber).First(&refreshed)
|
||||||
assert.Equal(t, sig, refreshed.Signature)
|
assert.Equal(t, sig, refreshed.Signature)
|
||||||
|
assert.Equal(t, responsibleSig, refreshed.ResponsibleSignature)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAftersalesService_CustomerConfirm_AuthorizeRejectsEmptySignature(t *testing.T) {
|
func TestAftersalesService_CustomerConfirm_AuthorizeRejectsEmptySignature(t *testing.T) {
|
||||||
@@ -246,6 +250,29 @@ func TestAftersalesService_CustomerConfirm_AuthorizeRejectsEmptySignature(t *tes
|
|||||||
_, err := svc.CustomerConfirm(order.SerialNumber, models.CustomerConfirmDTO{
|
_, err := svc.CustomerConfirm(order.SerialNumber, models.CustomerConfirmDTO{
|
||||||
Action: "authorize",
|
Action: "authorize",
|
||||||
Signature: "",
|
Signature: "",
|
||||||
|
ResponsibleSignature: validSignatureFixture(),
|
||||||
|
})
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "签名")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAftersalesService_CustomerConfirm_AuthorizeRejectsEmptyResponsibleSignature(t *testing.T) {
|
||||||
|
confirmTest(t)
|
||||||
|
owner := seedTechnician(t, "aftersales_empty_responsible_sig_owner")
|
||||||
|
defer database.DB.Unscoped().Delete(&owner)
|
||||||
|
|
||||||
|
order := createOrderFor(t, owner, "13800007778")
|
||||||
|
defer database.DB.Unscoped().Delete(order)
|
||||||
|
|
||||||
|
svc := AftersalesService{}
|
||||||
|
_, _ = svc.SubmitForConfirmation(order.SerialNumber, models.SubmitForConfirmationDTO{
|
||||||
|
ResolutionNote: "done",
|
||||||
|
}, owner)
|
||||||
|
|
||||||
|
_, err := svc.CustomerConfirm(order.SerialNumber, models.CustomerConfirmDTO{
|
||||||
|
Action: "authorize",
|
||||||
|
Signature: validSignatureFixture(),
|
||||||
|
ResponsibleSignature: "",
|
||||||
})
|
})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), "签名")
|
assert.Contains(t, err.Error(), "签名")
|
||||||
@@ -268,6 +295,7 @@ func TestAftersalesService_CustomerConfirm_AuthorizeRejectsInvalidSignature(t *t
|
|||||||
_, err := svc.CustomerConfirm(order.SerialNumber, models.CustomerConfirmDTO{
|
_, err := svc.CustomerConfirm(order.SerialNumber, models.CustomerConfirmDTO{
|
||||||
Action: "authorize",
|
Action: "authorize",
|
||||||
Signature: "not-a-data-url",
|
Signature: "not-a-data-url",
|
||||||
|
ResponsibleSignature: validSignatureFixture(),
|
||||||
})
|
})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), "签名格式")
|
assert.Contains(t, err.Error(), "签名格式")
|
||||||
@@ -277,6 +305,7 @@ func TestAftersalesService_CustomerConfirm_AuthorizeRejectsInvalidSignature(t *t
|
|||||||
_, err = svc.CustomerConfirm(order.SerialNumber, models.CustomerConfirmDTO{
|
_, err = svc.CustomerConfirm(order.SerialNumber, models.CustomerConfirmDTO{
|
||||||
Action: "authorize",
|
Action: "authorize",
|
||||||
Signature: tiny,
|
Signature: tiny,
|
||||||
|
ResponsibleSignature: validSignatureFixture(),
|
||||||
})
|
})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), "过短")
|
assert.Contains(t, err.Error(), "过短")
|
||||||
@@ -350,6 +379,7 @@ func TestAftersalesService_CustomerConfirm_RejectsWrongStatus(t *testing.T) {
|
|||||||
_, err := svc.CustomerConfirm(order.SerialNumber, models.CustomerConfirmDTO{
|
_, err := svc.CustomerConfirm(order.SerialNumber, models.CustomerConfirmDTO{
|
||||||
Action: "authorize",
|
Action: "authorize",
|
||||||
Signature: validSignatureFixture(),
|
Signature: validSignatureFixture(),
|
||||||
|
ResponsibleSignature: validSignatureFixture(),
|
||||||
})
|
})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user