@@ -13,11 +13,13 @@ import play.api.libs.json.Json
13
13
import play .api .libs .json .Json .toJsFieldJsValueWrapper
14
14
15
15
import org .elastic4play .JsonFormat .dateFormat
16
- import org .elastic4play .models .{ AttributeDef , AttributeFormat => F , AttributeOption => O , BaseEntity , EntityDef , HiveEnumeration , ModelDef }
16
+ import org .elastic4play .models .{ AttributeDef , AttributeFormat ⇒ F , AttributeOption ⇒ O , BaseEntity , EntityDef , HiveEnumeration , ModelDef }
17
17
import org .elastic4play .services .{ FindSrv , SequenceSrv }
18
18
19
19
import JsonFormat .{ caseImpactStatusFormat , caseResolutionStatusFormat , caseStatusFormat }
20
20
import services .AuditedModel
21
+ import services .CaseSrv
22
+ import play .api .Logger
21
23
22
24
object CaseStatus extends Enumeration with HiveEnumeration {
23
25
type Type = Value
@@ -34,7 +36,7 @@ object CaseImpactStatus extends Enumeration with HiveEnumeration {
34
36
val NoImpact, WithImpact, NotApplicable = Value
35
37
}
36
38
37
- trait CaseAttributes { _ : AttributeDef =>
39
+ trait CaseAttributes { _ : AttributeDef ⇒
38
40
val caseId = attribute(" caseId" , F .numberFmt, " Id of the case (auto-generated)" , O .model)
39
41
val title = attribute(" title" , F .textFmt, " Title of the case" )
40
42
val description = attribute(" description" , F .textFmt, " Description of the case" )
@@ -50,58 +52,111 @@ trait CaseAttributes { _: AttributeDef =>
50
52
val resolutionStatus = optionalAttribute(" resolutionStatus" , F .enumFmt(CaseResolutionStatus ), " Resolution status of the case" )
51
53
val impactStatus = optionalAttribute(" impactStatus" , F .enumFmt(CaseImpactStatus ), " Impact status of the case" )
52
54
val summary = optionalAttribute(" summary" , F .textFmt, " Summary of the case, to be provided when closing a case" )
53
- val mergeInto = optionalAttribute(" mergeInto" ,F .stringFmt, " Id of the case created by the merge" )
54
- val mergeFrom = multiAttribute(" mergeFrom" ,F .stringFmt, " Id of the cases merged" )
55
+ val mergeInto = optionalAttribute(" mergeInto" , F .stringFmt, " Id of the case created by the merge" )
56
+ val mergeFrom = multiAttribute(" mergeFrom" , F .stringFmt, " Id of the cases merged" )
55
57
}
56
58
57
59
@ Singleton
58
60
class CaseModel @ Inject () (
59
61
artifactModel : Provider [ArtifactModel ],
60
62
taskModel : Provider [TaskModel ],
63
+ caseSrv : Provider [CaseSrv ],
61
64
sequenceSrv : SequenceSrv ,
62
65
findSrv : FindSrv ,
63
- implicit val ec : ExecutionContext ) extends ModelDef [CaseModel , Case ](" case" ) with CaseAttributes with AuditedModel { caseModel =>
66
+ implicit val ec : ExecutionContext ) extends ModelDef [CaseModel , Case ](" case" ) with CaseAttributes with AuditedModel { caseModel ⇒
67
+
68
+ lazy val logger = Logger (getClass)
64
69
override val defaultSortBy = Seq (" -startDate" )
65
70
override val removeAttribute = Json .obj(" status" -> CaseStatus .Deleted )
66
71
67
72
override def creationHook (parent : Option [BaseEntity ], attrs : JsObject ) = {
68
- sequenceSrv(" case" ).map { caseId =>
73
+ sequenceSrv(" case" ).map { caseId ⇒
69
74
attrs + (" caseId" -> JsNumber (caseId))
70
75
}
71
76
}
72
77
73
78
override def updateHook (entity : BaseEntity , updateAttrs : JsObject ): Future [JsObject ] = Future .successful {
74
79
(updateAttrs \ " status" ).asOpt[CaseStatus .Type ] match {
75
- case Some (CaseStatus .Resolved ) if ! updateAttrs.keys.contains(" endDate" ) =>
80
+ case Some (CaseStatus .Resolved ) if ! updateAttrs.keys.contains(" endDate" ) ⇒
76
81
updateAttrs + (" endDate" -> Json .toJson(new Date ))
77
- case Some (CaseStatus .Open ) =>
82
+ case Some (CaseStatus .Open ) ⇒
78
83
updateAttrs + (" endDate" -> JsArray (Nil ))
79
- case _ =>
84
+ case _ ⇒
80
85
updateAttrs
81
86
}
82
87
}
83
88
84
- override def getStats ( entity : BaseEntity ): Future [JsObject ] = {
89
+ private [models] def buildArtifactStats ( caze : Case ): Future [JsObject ] = {
85
90
import org .elastic4play .services .QueryDSL ._
86
- for {
87
- taskStatsJson <- findSrv(
88
- taskModel.get,
89
- and(
90
- " _parent" ~= entity.id,
91
- " status" in (" Waiting" , " InProgress" , " Completed" )),
92
- groupByField(" status" , selectCount))
93
- (taskCount, taskStats) = taskStatsJson.value.foldLeft((0L , JsObject (Nil ))) {
94
- case ((total, s), (key, value)) =>
95
- val count = (value \ " count" ).as[Long ]
96
- (total + count, s + (key -> JsNumber (count)))
91
+ findSrv(
92
+ artifactModel.get,
93
+ and(
94
+ parent(" case" , withId(caze.id)),
95
+ " status" ~= " Ok" ),
96
+ selectCount)
97
+ .map { artifactStats ⇒
98
+ Json .obj(" artifacts" -> artifactStats)
99
+ }
100
+ }
101
+
102
+ private [models] def buildTaskStats (caze : Case ): Future [JsObject ] = {
103
+ import org .elastic4play .services .QueryDSL ._
104
+ findSrv(
105
+ taskModel.get,
106
+ and(
107
+ parent(" case" , withId(caze.id)),
108
+ " status" in (" Waiting" , " InProgress" , " Completed" )),
109
+ groupByField(" status" , selectCount))
110
+ .map { taskStatsJson ⇒
111
+ val (taskCount, taskStats) = taskStatsJson.value.foldLeft((0L , JsObject (Nil ))) {
112
+ case ((total, s), (key, value)) ⇒
113
+ val count = (value \ " count" ).as[Long ]
114
+ (total + count, s + (key -> JsNumber (count)))
115
+ }
116
+ Json .obj(" tasks" -> (taskStats + (" total" -> JsNumber (taskCount))))
117
+ }
118
+ }
119
+
120
+ private [models] def buildMergeIntoStats (caze : Case ): Future [JsObject ] = {
121
+ caze.mergeInto()
122
+ .fold(Future .successful(Json .obj())) { mergeCaseId ⇒
123
+ caseSrv.get.get(mergeCaseId).map { c ⇒
124
+ Json .obj(" mergeInto" -> Json .obj(
125
+ " caseId" -> c.caseId(),
126
+ " title" -> c.title()))
127
+ }
97
128
}
98
- artifactStats <- findSrv(
99
- artifactModel.get,
100
- and(
101
- " _parent" ~= entity.id,
102
- " status" ~= " Ok" ),
103
- selectCount)
104
- } yield Json .obj(" tasks" -> (taskStats + (" total" -> JsNumber (taskCount))), " artifacts" -> artifactStats)
129
+ }
130
+
131
+ private [models] def buildMergeFromStats (caze : Case ): Future [JsObject ] = {
132
+ Future
133
+ .traverse(caze.mergeFrom()) { id ⇒
134
+ caseSrv.get.get(id).map { c ⇒
135
+ Json .obj(
136
+ " caseId" -> c.caseId(),
137
+ " title" -> c.title())
138
+ }
139
+ }
140
+ .map {
141
+ case mf if ! mf.isEmpty ⇒ Json .obj(" mergeFrom" -> mf)
142
+ case _ ⇒ Json .obj()
143
+ }
144
+ }
145
+ override def getStats (entity : BaseEntity ): Future [JsObject ] = {
146
+
147
+
148
+ entity match {
149
+ case caze : Case ⇒
150
+ for {
151
+ taskStats <- buildTaskStats(caze)
152
+ artifactStats <- buildArtifactStats(caze)
153
+ mergeIntoStats <- buildMergeIntoStats(caze)
154
+ mergeFromStats <- buildMergeFromStats(caze)
155
+ } yield taskStats ++ artifactStats ++ mergeIntoStats ++ mergeFromStats
156
+ case other ⇒
157
+ logger.warn(s " Request caseStats from a non-case entity ?! ${other.getClass}: $other" )
158
+ Future .successful(Json .obj())
159
+ }
105
160
}
106
161
107
162
override val computedMetrics = Map (
0 commit comments