Skip to content

feat(customers): add time range filtering and count functionality to customer list endpoints#9767

Merged
likhinbopanna merged 26 commits intomainfrom
customer_count
Oct 16, 2025
Merged

feat(customers): add time range filtering and count functionality to customer list endpoints#9767
likhinbopanna merged 26 commits intomainfrom
customer_count

Conversation

@VenuMadhav2541
Copy link
Contributor

@VenuMadhav2541 VenuMadhav2541 commented Oct 9, 2025

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

  • Added time range filter support in the customer list API to fetch customers based on created_at between start_time and end_time.
  • Implemented count functionality to return both the filtered customer list and total count for pagination.
  • If customer_id is provided, the time range filter is skipped — only one filter applies at a time.

Additional Changes

  • This PR modifies the API contract
  • This PR modifies the database schema
  • This PR modifies application configuration/environment variables

Motivation and Context

  • This change enhances the customer list endpoints by adding time range filtering and count functionality. Previously, the API did not allow merchants to filter customers by their creation date, making it difficult to fetch customers within a specific time window.

  • Additionally, the count functionality enables accurate pagination on the client side by returning the total number of filtered customers along with the list.

  • Together, these improvements make the customer list API more flexible, efficient, and suitable for large datasets, improving the overall user experience for merchants.

How did you test it?

  1. Verified API manually with time_range[start_time] and time_range[end_time].
curl --location 'http://localhost:9000/api/customers/list_with_count?limit=20&offset=0&start_time=2025-10-06T18%3A30%3A00Z&end_time=2025-10-08T14%3A09%3A23Z' \
--header 'Accept: application/json' \
--header 'api-key: ••••••' \
--header 'Content-Type: text/plain' \
--data-binary '@'
  • Response
{
    "data": [
        {
            "customer_id": "cus_123",
            "name": "venu 12",
            "email": "guest@example.com",
            "phone": "999999999",
            "phone_country_code": "+65",
            "description": "First customer",
            "address": null,
            "created_at": "2025-10-08T08:10:06.395Z",
            "metadata": {
                "udf1": "value1",
                "new_customer": "true",
                "login_date": "2019-09-10T10:11:12Z"
            },
            "default_payment_method_id": null,
            "tax_registration_id": null
        },
        {
            "customer_id": "cus_124",
            "name": "venu 13",
            "email": "guest@example.com",
            "phone": "999999999",
            "phone_country_code": "+65",
            "description": "First customer",
            "address": null,
            "created_at": "2025-10-08T08:10:11.296Z",
            "metadata": {
                "udf1": "value1",
                "new_customer": "true",
                "login_date": "2019-09-10T10:11:12Z"
            },
            "default_payment_method_id": null,
            "tax_registration_id": null
        },
        {
            "customer_id": "cus_123125",
            "name": "venu 14",
            "email": "guest@example.com",
            "phone": "999999999",
            "phone_country_code": "+65",
            "description": "First customer",
            "address": null,
            "created_at": "2025-10-08T08:10:16.067Z",
            "metadata": {
                "udf1": "value1",
                "new_customer": "true",
                "login_date": "2019-09-10T10:11:12Z"
            },
            "default_payment_method_id": null,
            "tax_registration_id": null
        }
    ],
    "count": 22
}
  1. Verified API manually with time_range[start_time].
curl --location 'http://localhost:9000/api/customers/list_with_count?limit=20&offset=0&start_time=2025-10-06T18%3A30%3A00Z' \
--header 'Accept: application/json' \
--header 'api-key: ••••••' \
--header 'Content-Type: text/plain' \
--data-binary '@'
  • Response:
{
    "data": [
        {
            "customer_id": "cus_123",
            "name": "venu 12",
            "email": "guest@example.com",
            "phone": "999999999",
            "phone_country_code": "+65",
            "description": "First customer",
            "address": null,
            "created_at": "2025-10-08T08:10:06.395Z",
            "metadata": {
                "udf1": "value1",
                "new_customer": "true",
                "login_date": "2019-09-10T10:11:12Z"
            },
            "default_payment_method_id": null,
            "tax_registration_id": null
        },
        {
            "customer_id": "cus_124",
            "name": "venu 13",
            "email": "guest@example.com",
            "phone": "999999999",
            "phone_country_code": "+65",
            "description": "First customer",
            "address": null,
            "created_at": "2025-10-08T08:10:11.296Z",
            "metadata": {
                "udf1": "value1",
                "new_customer": "true",
                "login_date": "2019-09-10T10:11:12Z"
            },
            "default_payment_method_id": null,
            "tax_registration_id": null
        },
        {
            "customer_id": "cus_123125",
            "name": "venu 14",
            "email": "guest@example.com",
            "phone": "999999999",
            "phone_country_code": "+65",
            "description": "First customer",
            "address": null,
            "created_at": "2025-10-08T08:10:16.067Z",
            "metadata": {
                "udf1": "value1",
                "new_customer": "true",
                "login_date": "2019-09-10T10:11:12Z"
            },
            "default_payment_method_id": null,
            "tax_registration_id": null
        }
    ],
    "count": 22
}
  1. Verified API manually with Customer_Id and Time Range.
curl --location 'http://localhost:9000/api/customers/list_with_count?limit=20&offset=0&start_time=2025-10-06T18%3A30%3A00Z&end_time=2025-10-08T14%3A09%3A23Z&customer_id=cus_123' \
--header 'Accept: application/json' \
--header 'api-key: ••••••' \
--header 'Content-Type: text/plain' \
--data-binary '@'
  • Response:
{
    "data": [
        {
            "customer_id": "cus_123",
            "name": "venu 12",
            "email": "guest@example.com",
            "phone": "999999999",
            "phone_country_code": "+65",
            "description": "First customer",
            "address": null,
            "created_at": "2025-10-08T08:10:06.395Z",
            "metadata": {
                "udf1": "value1",
                "new_customer": "true",
                "login_date": "2019-09-10T10:11:12Z"
            },
            "default_payment_method_id": null,
            "tax_registration_id": null
        }
    ],
    "count": 22
}

Checklist

  • I formatted the code cargo +nightly fmt --all
  • I addressed lints thrown by cargo clippy
  • I reviewed the submitted code
  • I added unit tests for my changes where possible

@VenuMadhav2541 VenuMadhav2541 requested review from a team as code owners October 9, 2025 09:20
@semanticdiff-com
Copy link

semanticdiff-com bot commented Oct 9, 2025

@VenuMadhav2541 VenuMadhav2541 self-assigned this Oct 9, 2025
@VenuMadhav2541 VenuMadhav2541 added the C-feature Category: Feature request or enhancement label Oct 9, 2025
@VenuMadhav2541 VenuMadhav2541 linked an issue Oct 9, 2025 that may be closed by this pull request
2 tasks
@VenuMadhav2541 VenuMadhav2541 changed the title feat(customers): add time range filtering and count functionality to … feat(customers): add time range filtering and count functionality to customer list endpoints Oct 9, 2025
/// List of customers
pub data: Vec<CustomerResponse>,
/// Total count of customers
pub count: usize,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we call it total_count? count can be the size of data list like we have in other apis.

@VenuMadhav2541 VenuMadhav2541 requested a review from a team as a code owner October 15, 2025 10:06

impl ApiEventMetric for CustomerListResponse {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this None?

AER::InternalServerError(ApiError::new("HE", 0, "Something went wrong", None))
}
Self::InvalidRequestData { message } => {
AER::BadRequest(ApiError::new("IR", 400, message, None))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pass appropriate values as per this doc. https://api-reference.hyperswitch.io/essentials/error_codes

Also pass some meaningful error message

pub const CUSTOMER_LIST_UPPER_LIMIT: u16 = 100;
pub const CUSTOMER_LIST_DEFAULT_LIMIT: u16 = 10;

pub fn validate_customer_list_limit(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can have a domain wrapper type for u16. Which can only exist if the value is within 1 and 100. And 10 as default trait impl.

refer to https://github.com/juspay/hyperswitch/blob/main/crates/common_types/src/primitive_wrappers.rs

pub async fn list_customers_with_count(
state: SessionState,
merchant_id: id_type::MerchantId,
_profile_id_list: Option<Vec<id_type::ProfileId>>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed if not used

@hrithikesh026
Copy link
Contributor

Also start_time and end_time is not very descriptive.

created_lt, created_lte created_gt would be nice.

Comment on lines 593 to 595
customer_id: None,
time_range: None,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is changed to None?

) -> errors::CustomerResponse<customers::CustomerListResponse> {
let db = state.store.as_ref();
let limit =
crate::core::utils::customer_validation::validate_customer_list_limit(request.limit)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick*: Instead of bid qualification paths, we can import some part always, and then qualify it as utils::something, and this can be done at most of the places.

Copy link
Contributor

@hrithikesh026 hrithikesh026 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please Generate Openapi spec for the new api. If not here, then in a separate PR.

@likhinbopanna likhinbopanna added this pull request to the merge queue Oct 16, 2025
Merged via the queue into main with commit 587588f Oct 16, 2025
22 of 25 checks passed
@likhinbopanna likhinbopanna deleted the customer_count branch October 16, 2025 08:13
chaitak-gorai pushed a commit that referenced this pull request Oct 16, 2025
…customer list endpoints (#9767)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
drdholu pushed a commit to drdholu/hyperswitch that referenced this pull request Oct 30, 2025
…customer list endpoints (juspay#9767)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
aadityaguptaa pushed a commit that referenced this pull request Nov 10, 2025
…customer list endpoints (#9767)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-feature Category: Feature request or enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Add filter and Pagination in Customer Page

7 participants