Skip to content

Commit

Permalink
feat: refunds failure distribution (#1937)
Browse files Browse the repository at this point in the history
  • Loading branch information
sagarnaikjuspay authored Dec 17, 2024
1 parent fdab784 commit bcf649b
Show file tree
Hide file tree
Showing 5 changed files with 331 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
open NewAnalyticsTypes
open NewAnalyticsHelper
open NewRefundsAnalyticsEntity
open BarGraphTypes
open FailedRefundsDistributionUtils
open FailedRefundsDistributionTypes

module TableModule = {
@react.component
let make = (~data, ~className="") => {
let (offset, setOffset) = React.useState(_ => 0)
let defaultSort: Table.sortedObject = {
key: "",
order: Table.INC,
}

let visibleColumns = [Connector, Refunds_Failure_Rate]
let tableData = getTableData(data)

<div className>
<LoadedTable
visibleColumns
title=" "
hideTitle=true
actualData={tableData}
entity=failedRefundsDistributionTableEntity
resultsPerPage=10
totalResults={tableData->Array.length}
offset
setOffset
defaultSort
currrentFetchCount={tableData->Array.length}
tableLocalFilter=false
tableheadingClass=tableBorderClass
tableBorderClass
ignoreHeaderBg=true
tableDataBorderClass=tableBorderClass
isAnalyticsModule=true
/>
</div>
}
}

module FailedRefundsDistributionHeader = {
@react.component
let make = (~viewType, ~setViewType) => {
let setViewType = value => {
setViewType(_ => value)
}
<div className="w-full px-8 pt-3 pb-3 flex justify-end">
<div className="flex gap-2">
<TabSwitch viewType setViewType />
</div>
</div>
}
}

@react.component
let make = (
~entity: moduleEntity,
~chartEntity: chartEntity<barGraphPayload, barGraphOptions, JSON.t>,
) => {
open LogicUtils
open APIUtils
let getURL = useGetURL()
let updateDetails = useUpdateMethod()
let {filterValueJson} = React.useContext(FilterContext.filterContext)
let (screenState, setScreenState) = React.useState(_ => PageLoaderWrapper.Loading)

let (refundsDistribution, setrefundsDistribution) = React.useState(_ => JSON.Encode.array([]))
let (viewType, setViewType) = React.useState(_ => Graph)
let startTimeVal = filterValueJson->getString("startTime", "")
let endTimeVal = filterValueJson->getString("endTime", "")

let getRefundsDistribution = async () => {
setScreenState(_ => PageLoaderWrapper.Loading)
try {
let url = getURL(
~entityName=ANALYTICS_REFUNDS,
~methodType=Post,
~id=Some((entity.domain: domain :> string)),
)

let body = NewAnalyticsUtils.requestBody(
~startTime=startTimeVal,
~endTime=endTimeVal,
~delta=entity.requestBodyConfig.delta,
~metrics=entity.requestBodyConfig.metrics,
~groupByNames=[Connector->getStringFromVariant]->Some,
)

let response = await updateDetails(url, body, Post)

let responseTotalNumberData =
response->getDictFromJsonObject->getArrayFromDict("queryData", [])

if responseTotalNumberData->Array.length > 0 {
// TODO: need refactor on filters
let filters = Dict.make()
filters->Dict.set("refund_status", ["failure"->JSON.Encode.string]->JSON.Encode.array)

let body = NewAnalyticsUtils.requestBody(
~startTime=startTimeVal,
~endTime=endTimeVal,
~filter=filters->JSON.Encode.object->Some,
~delta=entity.requestBodyConfig.delta,
~metrics=entity.requestBodyConfig.metrics,
~groupByNames=[Connector->getStringFromVariant]->Some,
)

let response = await updateDetails(url, body, Post)

let responseFailedNumberData =
response->getDictFromJsonObject->getArrayFromDict("queryData", [])

setrefundsDistribution(_ =>
modifyQuery(responseTotalNumberData, responseFailedNumberData)->JSON.Encode.array
)

setScreenState(_ => PageLoaderWrapper.Success)
} else {
setScreenState(_ => PageLoaderWrapper.Custom)
}
} catch {
| _ => setScreenState(_ => PageLoaderWrapper.Custom)
}
}

React.useEffect(() => {
if startTimeVal->isNonEmptyString && endTimeVal->isNonEmptyString {
getRefundsDistribution()->ignore
}
None
}, [startTimeVal, endTimeVal])

let params = {
data: refundsDistribution,
xKey: Refunds_Failure_Rate->getStringFromVariant,
yKey: Connector->getStringFromVariant,
}

<div>
<ModuleHeader title={entity.title} />
<Card>
<PageLoaderWrapper
screenState customLoader={<Shimmer layoutId=entity.title />} customUI={<NoData />}>
<FailedRefundsDistributionHeader viewType setViewType />
<div className="mb-5">
{switch viewType {
| Graph =>
<BarGraph
entity={chartEntity} object={chartEntity.getObjects(~params)} className="mr-3"
/>
| Table => <TableModule data={refundsDistribution} className="mx-7" />
}}
</div>
</PageLoaderWrapper>
</Card>
</div>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
type failedRefundsDistributionTypes =
| Refunds_Failure_Rate
| Refund_Count
| Connector

type failedRefundsDistributionObject = {
refund_count: int,
refunds_failure_rate: float,
connector: string,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
open NewAnalyticsUtils
open LogicUtils
open FailedRefundsDistributionTypes

let getStringFromVariant = value => {
switch value {
| Refunds_Failure_Rate => "refunds_failure_rate"
| Refund_Count => "refund_count"
| Connector => "connector"
}
}

let failedRefundsDistributionMapper = (
~params: NewAnalyticsTypes.getObjects<JSON.t>,
): BarGraphTypes.barGraphPayload => {
open BarGraphTypes
let {data, xKey, yKey} = params
let categories = [data]->JSON.Encode.array->getCategories(0, yKey)

let barGraphData = getBarGraphObj(
~array=data->getArrayFromJson([]),
~key=xKey,
~name=xKey->snakeToTitle,
~color=redColor,
)
let title = {
text: "",
}

{
categories,
data: [barGraphData],
title,
tooltipFormatter: bargraphTooltipFormatter(
~title="Failed Refunds Distribution",
~metricType=Rate,
),
}
}

let tableItemToObjMapper: Dict.t<JSON.t> => failedRefundsDistributionObject = dict => {
{
refund_count: dict->getInt(Refund_Count->getStringFromVariant, 0),
refunds_failure_rate: dict->getFloat(Refunds_Failure_Rate->getStringFromVariant, 0.0),
connector: dict->getString(Connector->getStringFromVariant, ""),
}
}

let getObjects: JSON.t => array<failedRefundsDistributionObject> = json => {
json
->LogicUtils.getArrayFromJson([])
->Array.map(item => {
tableItemToObjMapper(item->getDictFromJsonObject)
})
}

let getHeading = colType => {
switch colType {
| Refunds_Failure_Rate =>
Table.makeHeaderInfo(
~key=Refunds_Failure_Rate->getStringFromVariant,
~title="Refunds Failure Rate",
~dataType=TextType,
)
| Connector =>
Table.makeHeaderInfo(
~key=Connector->getStringFromVariant,
~title="Connector",
~dataType=TextType,
)
| _ => Table.makeHeaderInfo(~key="", ~title="", ~dataType=TextType)
}
}

let getCell = (obj, colType): Table.cell => {
switch colType {
| Refunds_Failure_Rate => Text(obj.refunds_failure_rate->valueFormatter(Rate))
| Connector => Text(obj.connector)
| _ => Text("")
}
}

let getTableData = json => {
json->getArrayDataFromJson(tableItemToObjMapper)->Array.map(Nullable.make)
}

let modifyQuery = (totalCountArr, failureCountArr) => {
let mapper = Dict.make()

totalCountArr->Array.forEach(item => {
let valueDict = item->getDictFromJsonObject
let key = valueDict->getString(Connector->getStringFromVariant, "")

if key->isNonEmptyString {
mapper->Dict.set(key, item)
}
})

failureCountArr->Array.forEach(item => {
let itemDict = item->getDictFromJsonObject
let key = itemDict->getString(Connector->getStringFromVariant, "")

switch mapper->Dict.get(key) {
| Some(value) => {
let valueDict = value->getDictFromJsonObject

let failureCount = itemDict->getInt(Refund_Count->getStringFromVariant, 0)->Int.toFloat
let totalCount = valueDict->getInt(Refund_Count->getStringFromVariant, 0)->Int.toFloat

let failureRate = totalCount > 0.0 ? failureCount /. totalCount *. 100.0 : 0.0

valueDict->Dict.set(
Refunds_Failure_Rate->getStringFromVariant,
failureRate->JSON.Encode.float,
)

mapper->Dict.set(key, valueDict->JSON.Encode.object)
}
| _ => ()
}
})

mapper->Dict.valuesToArray
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ let make = () => {
<RefundsSuccessRate
entity={refundsSuccessRateEntity} chartEntity={refundsSuccessRateChartEntity}
/>
<FailedRefundsDistribution
entity={failedRefundsDistributionEntity} chartEntity={failedRefundsDistributionChartEntity}
/>
<SuccessfulRefundsDistribution
entity={successfulRefundsDistributionEntity}
chartEntity={successfulRefundsDistributionChartEntity}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,40 @@ let successfulRefundsDistributionTableEntity = {
)
}

// Failed Refunds Distribution
let failedRefundsDistributionEntity: moduleEntity = {
requestBodyConfig: {
delta: false,
groupBy: [#connector],
metrics: [#sessionized_refund_count],
},
title: "Failed Refunds Distribution By Connector",
domain: #refunds,
}

let failedRefundsDistributionChartEntity: chartEntity<
BarGraphTypes.barGraphPayload,
BarGraphTypes.barGraphOptions,
JSON.t,
> = {
getObjects: FailedRefundsDistributionUtils.failedRefundsDistributionMapper,
getChatOptions: BarGraphUtils.getBarGraphOptions,
}

let failedRefundsDistributionTableEntity = {
open FailedRefundsDistributionUtils
EntityType.makeEntity(
~uri=``,
~getObjects,
~dataKey="queryData",
~defaultColumns=[],
~requiredSearchFieldsList=[],
~allColumns=[],
~getCell,
~getHeading,
)
}

// Refunds Reasons
let refundsReasonsEntity: moduleEntity = {
requestBodyConfig: {
Expand Down

0 comments on commit bcf649b

Please sign in to comment.