feat(t215): add admin order authorization
This commit is contained in:
@@ -14,20 +14,23 @@ import (
|
||||
const localAdminSubject = "local-admin"
|
||||
|
||||
type UsecaseAdapter struct {
|
||||
tasks *usecase.TaskService
|
||||
assets *usecase.AssetService
|
||||
tasks *usecase.TaskService
|
||||
assets *usecase.AssetService
|
||||
authorizations *usecase.OrderAuthorizationService
|
||||
}
|
||||
|
||||
func NewUsecaseAdapter(
|
||||
tasks *usecase.TaskService,
|
||||
assets *usecase.AssetService,
|
||||
authorizations *usecase.OrderAuthorizationService,
|
||||
) (*UsecaseAdapter, error) {
|
||||
if tasks == nil || assets == nil {
|
||||
if tasks == nil || assets == nil || authorizations == nil {
|
||||
return nil, errors.New("admin web use cases are required")
|
||||
}
|
||||
return &UsecaseAdapter{
|
||||
tasks: tasks,
|
||||
assets: assets,
|
||||
tasks: tasks,
|
||||
assets: assets,
|
||||
authorizations: authorizations,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -146,6 +149,70 @@ func (adapter *UsecaseAdapter) CancelTask(
|
||||
return taskFromPurchase(task), nil
|
||||
}
|
||||
|
||||
func (adapter *UsecaseAdapter) AuthorizeOrder(
|
||||
ctx context.Context,
|
||||
input AuthorizeOrderInput,
|
||||
) (OrderAuthorization, error) {
|
||||
detail, err := adapter.tasks.Get(ctx, localAdminSubject, input.TaskID)
|
||||
if err != nil {
|
||||
return OrderAuthorization{}, mapUsecaseError(err)
|
||||
}
|
||||
if detail.Task.Version != input.ExpectedTaskVersion ||
|
||||
detail.Execution == nil ||
|
||||
detail.Report == nil ||
|
||||
detail.Report.DecisionDataset == nil {
|
||||
return OrderAuthorization{}, ErrConflict
|
||||
}
|
||||
var supersedes *string
|
||||
if input.SupersedesAuthorizationID != "" {
|
||||
value := input.SupersedesAuthorizationID
|
||||
supersedes = &value
|
||||
}
|
||||
items := make(
|
||||
[]usecase.OrderAuthorizationItemInput,
|
||||
0,
|
||||
len(detail.Report.DecisionDataset.Observations),
|
||||
)
|
||||
for _, observation := range detail.Report.DecisionDataset.Observations {
|
||||
if observation.Identity == nil {
|
||||
return OrderAuthorization{}, ErrConflict
|
||||
}
|
||||
label := "REJECT"
|
||||
reason := input.RejectedReasonCode
|
||||
if observation.Identity.CandidateKey == input.CandidateKey {
|
||||
label = "ACCEPT"
|
||||
reason = input.SelectedReasonCode
|
||||
}
|
||||
items = append(items, usecase.OrderAuthorizationItemInput{
|
||||
CandidateKey: observation.Identity.CandidateKey,
|
||||
Label: label,
|
||||
PrimaryReasonCode: reason,
|
||||
ReasonCodes: []string{reason},
|
||||
})
|
||||
}
|
||||
result, err := adapter.authorizations.Create(
|
||||
ctx,
|
||||
usecase.CreateOrderAuthorizationCommand{
|
||||
ActorUserID: actorUserID(ctx),
|
||||
TaskID: input.TaskID,
|
||||
IdempotencyKey: input.IdempotencyKey,
|
||||
ExecutionID: detail.Execution.ID,
|
||||
TaskContentSHA256: usecase.TaskContentSHA256(detail.Task),
|
||||
ExpectedTaskVersion: input.ExpectedTaskVersion,
|
||||
CandidateKey: input.CandidateKey,
|
||||
ReasonSchemaVersion: 1,
|
||||
PrimaryReasonCode: "SELECTED_BEST_MATCH",
|
||||
Note: input.Note,
|
||||
SupersedesAuthorizationID: supersedes,
|
||||
Items: items,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return OrderAuthorization{}, mapUsecaseError(err)
|
||||
}
|
||||
return orderAuthorizationFrom(result.Authorization), nil
|
||||
}
|
||||
|
||||
func taskSummaryFrom(task domain.PurchaseTask) TaskSummary {
|
||||
return TaskSummary{
|
||||
ID: task.ID,
|
||||
@@ -177,11 +244,64 @@ func taskFromPurchase(task domain.PurchaseTask) Task {
|
||||
|
||||
func taskFromDetail(detail domain.TaskDetail) Task {
|
||||
task := taskFromPurchase(detail.Task)
|
||||
task.Version = detail.Task.Version
|
||||
task.ReferenceAssetID = detail.Asset.ID
|
||||
task.ExecutionReport = executionReportFrom(detail.Report)
|
||||
task.TaskContentSHA256 = usecase.TaskContentSHA256(detail.Task)
|
||||
if detail.Execution != nil {
|
||||
task.ExecutionID = detail.Execution.ID
|
||||
}
|
||||
if detail.Report != nil && detail.Report.DecisionDataset != nil {
|
||||
for _, observation := range detail.Report.DecisionDataset.Observations {
|
||||
if observation.Identity == nil {
|
||||
continue
|
||||
}
|
||||
candidate := AuthorizationCandidate{
|
||||
CandidateKey: observation.Identity.CandidateKey,
|
||||
Ordinal: observation.Ordinal,
|
||||
Title: observation.Title,
|
||||
SKUText: observation.SKUText,
|
||||
PriceText: observation.PriceText,
|
||||
EvidenceURLs: make([]string, 0, len(observation.EvidenceAssetIDs)),
|
||||
}
|
||||
for _, evidenceID := range observation.EvidenceAssetIDs {
|
||||
candidate.EvidenceURLs = append(
|
||||
candidate.EvidenceURLs,
|
||||
"/api/v1/tasks/"+detail.Task.ID+
|
||||
"/evidence/"+evidenceID+"/content",
|
||||
)
|
||||
}
|
||||
task.Candidates = append(task.Candidates, candidate)
|
||||
}
|
||||
}
|
||||
for _, authorization := range detail.OrderAuthorizations {
|
||||
task.OrderAuthorizations = append(
|
||||
task.OrderAuthorizations,
|
||||
orderAuthorizationFrom(authorization),
|
||||
)
|
||||
}
|
||||
return task
|
||||
}
|
||||
|
||||
func orderAuthorizationFrom(
|
||||
authorization domain.OrderAuthorization,
|
||||
) OrderAuthorization {
|
||||
result := OrderAuthorization{
|
||||
ID: authorization.ID,
|
||||
Version: authorization.AuthorizationVersion,
|
||||
CandidateKey: authorization.CandidateKey,
|
||||
CandidateSKUText: authorization.CandidateSKUText,
|
||||
CandidatePriceText: authorization.CandidatePriceText,
|
||||
Quantity: authorization.Quantity,
|
||||
Status: string(authorization.Status),
|
||||
CreatedAt: authorization.CreatedAt,
|
||||
}
|
||||
if authorization.SupersedesAuthorizationID != nil {
|
||||
result.SupersedesID = *authorization.SupersedesAuthorizationID
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func executionReportFrom(report *domain.ExecutionReport) *ExecutionReport {
|
||||
if report == nil {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user