From bcf649bb582d2e1bbf717b1b9a78d2249c44b654 Mon Sep 17 00:00:00 2001 From: Sagar naik Date: Tue, 17 Dec 2024 18:18:36 +0530 Subject: [PATCH] feat: refunds failure distribution (#1937) --- .../FailedRefundsDistribution.res | 160 ++++++++++++++++++ .../FailedRefundsDistributionTypes.res | 10 ++ .../FailedRefundsDistributionUtils.res | 124 ++++++++++++++ .../NewRefundsAnalytics.res | 3 + .../NewRefundsAnalyticsEntity.res | 34 ++++ 5 files changed, 331 insertions(+) create mode 100644 src/screens/NewAnalytics/NewRefundsAnalytics/FailedRefundsDistribution/FailedRefundsDistribution.res create mode 100644 src/screens/NewAnalytics/NewRefundsAnalytics/FailedRefundsDistribution/FailedRefundsDistributionTypes.res create mode 100644 src/screens/NewAnalytics/NewRefundsAnalytics/FailedRefundsDistribution/FailedRefundsDistributionUtils.res diff --git a/src/screens/NewAnalytics/NewRefundsAnalytics/FailedRefundsDistribution/FailedRefundsDistribution.res b/src/screens/NewAnalytics/NewRefundsAnalytics/FailedRefundsDistribution/FailedRefundsDistribution.res new file mode 100644 index 000000000..ec663d2b6 --- /dev/null +++ b/src/screens/NewAnalytics/NewRefundsAnalytics/FailedRefundsDistribution/FailedRefundsDistribution.res @@ -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) + +
+ Array.length} + offset + setOffset + defaultSort + currrentFetchCount={tableData->Array.length} + tableLocalFilter=false + tableheadingClass=tableBorderClass + tableBorderClass + ignoreHeaderBg=true + tableDataBorderClass=tableBorderClass + isAnalyticsModule=true + /> +
+ } +} + +module FailedRefundsDistributionHeader = { + @react.component + let make = (~viewType, ~setViewType) => { + let setViewType = value => { + setViewType(_ => value) + } +
+
+ +
+
+ } +} + +@react.component +let make = ( + ~entity: moduleEntity, + ~chartEntity: chartEntity, +) => { + 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, + } + +
+ + + } customUI={}> + +
+ {switch viewType { + | Graph => + + | Table => + }} +
+
+
+
+} diff --git a/src/screens/NewAnalytics/NewRefundsAnalytics/FailedRefundsDistribution/FailedRefundsDistributionTypes.res b/src/screens/NewAnalytics/NewRefundsAnalytics/FailedRefundsDistribution/FailedRefundsDistributionTypes.res new file mode 100644 index 000000000..cd5a52aa8 --- /dev/null +++ b/src/screens/NewAnalytics/NewRefundsAnalytics/FailedRefundsDistribution/FailedRefundsDistributionTypes.res @@ -0,0 +1,10 @@ +type failedRefundsDistributionTypes = + | Refunds_Failure_Rate + | Refund_Count + | Connector + +type failedRefundsDistributionObject = { + refund_count: int, + refunds_failure_rate: float, + connector: string, +} diff --git a/src/screens/NewAnalytics/NewRefundsAnalytics/FailedRefundsDistribution/FailedRefundsDistributionUtils.res b/src/screens/NewAnalytics/NewRefundsAnalytics/FailedRefundsDistribution/FailedRefundsDistributionUtils.res new file mode 100644 index 000000000..c0044ce59 --- /dev/null +++ b/src/screens/NewAnalytics/NewRefundsAnalytics/FailedRefundsDistribution/FailedRefundsDistributionUtils.res @@ -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, +): 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 => 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 = 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 +} diff --git a/src/screens/NewAnalytics/NewRefundsAnalytics/NewRefundsAnalytics.res b/src/screens/NewAnalytics/NewRefundsAnalytics/NewRefundsAnalytics.res index 95ed9c3e7..f0d74976a 100644 --- a/src/screens/NewAnalytics/NewRefundsAnalytics/NewRefundsAnalytics.res +++ b/src/screens/NewAnalytics/NewRefundsAnalytics/NewRefundsAnalytics.res @@ -8,6 +8,9 @@ let make = () => { + = { + 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: {