Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Payouts endpoints #124

Merged
merged 18 commits into from
Mar 31, 2024
Merged

Payouts endpoints #124

merged 18 commits into from
Mar 31, 2024

Conversation

jamalsoueidan
Copy link
Owner

@jamalsoueidan jamalsoueidan commented Mar 31, 2024

Type

enhancement, bug_fix


Description

  • Added Azure functions and controllers for customer payout operations including balance, get, and paginate.
  • Implemented services for customer payout log pagination, payout balance calculation, payout creation, and payout pagination.
  • Refactored payout log schema to support multiple reference types and added indexing to certain fields in LineItemSchema.
  • Added tests for new services and updated Zod schemas and types.
  • Updated API documentation to include new customer payout and payout log endpoints.

Changes walkthrough

Relevant files
Enhancement
19 files
customer-payout-log.function.ts
Add Azure Function for Customer Payout Log Pagination       

src/functions/customer-payout-log.function.ts

  • Added Azure function for customer payout log pagination.
+12/-0   
customer-payout.functions.ts
Add Azure Functions for Customer Payout Operations             

src/functions/customer-payout.functions.ts

  • Added Azure functions for customer payout operations including
    balance, get, and paginate.
  • +28/-0   
    paginate.ts
    Implement Controller for Customer Payout Log Pagination   

    src/functions/customer/controllers/payout-log/paginate.ts

    • Implemented controller for customer payout log pagination.
    +33/-0   
    balance.ts
    Implement Controller for Fetching Customer Payout Balance

    src/functions/customer/controllers/payout/balance.ts

    • Implemented controller for fetching customer payout balance.
    +23/-0   
    get.ts
    Implement Controller for Fetching a Single Customer Payout

    src/functions/customer/controllers/payout/get.ts

    • Implemented controller for fetching a single customer payout.
    +24/-0   
    paginate.ts
    Implement Controller for Customer Payout Pagination           

    src/functions/customer/controllers/payout/paginate.ts

    • Implemented controller for customer payout pagination.
    +32/-0   
    list.ts
    Refactor Customer Blocked Service List for hasNextPage Logic

    src/functions/customer/services/blocked/list.ts

  • Refactored customer blocked service list to support hasNextPage logic.

  • +8/-13   
    paginate.ts
    Implement Service for Customer Payout Log Pagination         

    src/functions/customer/services/payout-log/paginate.ts

    • Implemented service for customer payout log pagination.
    +119/-0 
    aggregation.ts
    Add Aggregation Pipelines for Payout Calculations               

    src/functions/customer/services/payout/aggregation.ts

    • Added aggregation pipelines for payout calculations.
    +115/-0 
    balance.ts
    Implement Service for Calculating Customer Payout Balance

    src/functions/customer/services/payout/balance.ts

    • Implemented service for calculating customer payout balance.
    +29/-55 
    create.ts
    Implement Service for Creating Customer Payouts                   

    src/functions/customer/services/payout/create.ts

    • Implemented service for creating customer payouts.
    +109/-0 
    get.ts
    Implement Service for Fetching a Single Customer Payout   

    src/functions/customer/services/payout/get.ts

    • Implemented service for fetching a single customer payout.
    +26/-0   
    paginate.ts
    Implement Service for Customer Payout Pagination                 

    src/functions/customer/services/payout/paginate.ts

    • Implemented service for customer payout pagination.
    +38/-0   
    order.schema.ts
    Add Indexing to LineItemSchema Fields                                       

    src/functions/order/order.schema.ts

  • Added indexing to current_quantity, fulfillable_quantity, and
    fulfillment_status in LineItemSchema.
  • +3/-3     
    payout-log.schema.ts
    Refactor Payout Log Schema for Multiple Reference Types   

    src/functions/payout-log/payout-log.schema.ts

    • Refactored payout log schema to support multiple reference types.
    +12/-6   
    payout-log.types.ts
    Update PayoutLogZodSchema and Add PayoutLogReferenceType Enum

    src/functions/payout-log/payout-log.types.ts

    • Updated PayoutLogZodSchema and added PayoutLogReferenceType enum.
    +7/-2     
    list.ts
    Refactor UserServiceList to Use Page Numbers                         

    src/functions/user/services/user/list.ts

    • Refactored UserServiceList to use page numbers instead of cursors.
    +8/-6     
    shipping.ts
    Allow Custom customerId in createShipping Helper Function

    src/library/jest/helpers/shipping.ts

    • Allow custom customerId in createShipping helper function.
    +5/-3     
    index.ts
    Update Zod Schemas and Types                                                         

    src/library/zod/index.ts

    • Updated Zod schemas and types.
    +2/-0     
    Tests
    9 files
    paginate.spec.ts
    Add Tests for Customer Payout Log Pagination Service         

    src/functions/customer/services/payout-log/paginate.spec.ts

    • Added tests for customer payout log pagination service.
    +57/-0   
    balance.spec.ts
    Add Tests for Customer Payout Balance Service                       

    src/functions/customer/services/payout/balance.spec.ts

    • Added tests for customer payout balance service.
    +44/-15 
    create.spec.ts
    Add Tests for Customer Payout Creation Service                     

    src/functions/customer/services/payout/create.spec.ts

    • Added tests for customer payout creation service.
    +87/-0   
    get.spec.ts
    Add Tests for Customer Payout Get Service                               

    src/functions/customer/services/payout/get.spec.ts

    • Added tests for customer payout get service.
    +55/-0   
    paginate.spec.ts
    Add Tests for Customer Payout Pagination Service                 

    src/functions/customer/services/payout/paginate.spec.ts

    • Added tests for customer payout pagination service.
    +83/-0   
    generate.spec.ts
    Set Up Fake Timers in Tests for Availability Generation   

    src/functions/user/services/availability/generate.spec.ts

    • Set up fake timers in tests for availability generation.
    +32/-11 
    get.spec.ts
    Set Up Fake Timers in Tests for Availability Get Service 

    src/functions/user/services/availability/get.spec.ts

    • Set up fake timers in tests for availability get service.
    +27/-7   
    generate-availability.spec.ts
    Set Up Fake Timers in Tests for Availability Generation   

    src/library/availability/generate-availability.spec.ts

    • Set up fake timers in tests for availability generation.
    +20/-0   
    payout.ts
    Add Helper Functions for Creating Payout in Tests               

    src/library/jest/helpers/payout.ts

    • Added helper functions for creating payout in tests.
    +22/-0   
    Bug_fix
    3 files
    dummydata.balance.ts
    Remove default_address from Payout Fixtures                           

    src/functions/customer/services/payout/fixtures/dummydata.balance.ts

    • Removed default_address from dummyDataBalance in payout fixtures.
    +0/-19   
    generate.ts
    Remove toDate from Availability Service Generate Function

    src/functions/user/services/availability/generate.ts

    • Removed toDate from availability service generate function.
    +0/-2     
    list.spec.ts
    Rename 'total' to 'totalCount' in UserServiceList Tests   

    src/functions/user/services/user/list.spec.ts

    • Renamed 'total' to 'totalCount' in UserServiceList tests.
    +3/-3     
    Documentation
    1 files
    openapi.yaml
    Add API Documentation for Customer Payout and Payout Log Endpoints

    openapi/openapi.yaml

  • Added API documentation for new customer payout and payout log
    endpoints.
  • +38/-0   

    PR-Agent usage:
    Comment /help on the PR to get a list of all available PR-Agent tools and their descriptions

    @github-actions github-actions bot added enhancement New feature or request tests labels Mar 31, 2024
    Copy link

    PR Description updated to latest commit (b3bd380)

    Copy link

    PR Review

    ⏱️ Estimated effort to review [1-5]

    4, due to the complexity of the aggregation logic, the integration of new payout calculation logic, and the need to ensure that the refactored code does not introduce any bugs or performance issues. The addition of tests is a positive aspect, but the logic within the payout calculations and the handling of shipping costs require careful review to ensure accuracy and efficiency.

    🧪 Relevant tests

    Yes

    🔍 Possible issues

    Possible Bug: The aggregation logic in lineItemAggregation and shippingAggregation might not correctly handle edge cases where line items or shipping records do not meet expected criteria, potentially leading to incorrect payout calculations.

    Performance Concern: The use of $lookup and $unwind in MongoDB aggregations can be performance-intensive, especially with large datasets. Optimizing these queries or considering alternative approaches might be necessary.

    🔒 Security concerns

    No

    Code feedback:
    relevant filesrc/functions/customer/services/payout/aggregation.ts
    suggestion      

    Consider adding indexes on the fields used in the $match and $lookup stages of the aggregation pipelines to improve query performance. This is particularly important for fields like customerId, line_items.id, and line_items.properties.shippingId. [important]

    relevant lineimport { PipelineStage } from "mongoose";

    relevant filesrc/functions/customer/services/payout/create.ts
    suggestion      

    Ensure error handling for the case where CustomerPayoutAccountServiceGet does not find an account. Throwing a NotFoundError is good, but also consider logging this event or sending a notification, as it indicates a potential data integrity issue. [important]

    relevant lineconst account = await CustomerPayoutAccountServiceGet({ customerId });

    relevant filesrc/functions/customer/services/payout/balance.ts
    suggestion      

    For better code readability and maintenance, consider breaking down the large aggregation pipeline into smaller, well-named functions that describe each step's purpose. This will make the code easier to understand and debug. [medium]

    relevant line...lineItemAggregation({ customerId }),

    relevant filesrc/functions/customer/services/payout/create.spec.ts
    suggestion      

    Add more test cases to cover scenarios where line items or shipping costs should not be included in the payout due to various conditions (e.g., items already paid out, items not fulfilled). This will ensure the robustness of the payout calculation logic. [important]

    relevant linedescribe("CustomerPayoutServiceCreate", () => {


    ✨ Review tool usage guide:

    Overview:
    The review tool scans the PR code changes, and generates a PR review which includes several types of feedbacks, such as possible PR issues, security threats and relevant test in the PR. More feedbacks can be added by configuring the tool.

    The tool can be triggered automatically every time a new PR is opened, or can be invoked manually by commenting on any PR.

    • When commenting, to edit configurations related to the review tool (pr_reviewer section), use the following template:
    /review --pr_reviewer.some_config1=... --pr_reviewer.some_config2=...
    
    [pr_reviewer]
    some_config1=...
    some_config2=...
    

    See the review usage page for a comprehensive guide on using this tool.

    Copy link

    PR Code Suggestions

    CategorySuggestions                                                                                                                                                       
    Performance
    Add indexes to improve $lookup operation performance.

    Consider adding an index on the line_items.id and line_items.properties.shippingId fields
    in your MongoDB schema to improve the performance of the $lookup operations in your
    aggregation pipelines. These operations rely on matching these fields, and having indexes
    can significantly speed up query execution, especially for large datasets.

    src/functions/customer/services/payout/aggregation.ts [23-27]

    -{
    -  from: PayoutLogModel.collection.name,
    -  let: {
    -    referenceId: "$line_items.id",
    -    customerId: "$line_items.properties.customerId",
    -  },
    -  ...
    -}
    +// Ensure these indexes exist in your MongoDB schema:
    +// db.collection.createIndex({ "line_items.id": 1 })
    +// db.collection.createIndex({ "line_items.properties.shippingId": 1 })
     
    Evaluate the necessity of indexes to balance query performance and storage.

    Since you've added indexes to the current_quantity, fulfillable_quantity, and
    fulfillment_status fields in the LineItemSchema, consider whether these fields are
    frequently used in queries that benefit from these indexes. Adding indexes can improve
    query performance but also increases storage and can slow down write operations. Ensure
    that the benefits outweigh the costs in your specific use case.

    src/functions/order/order.schema.ts [112-115]

    -current_quantity: { type: Number, index: true },
    -fulfillable_quantity: { type: Number, index: true },
    -fulfillment_status: { type: String, index: true },
    +// If certain fields are not frequently queried, consider removing the indexes to optimize write performance and storage:
    +current_quantity: Number,
    +fulfillable_quantity: Number,
    +fulfillment_status: String,
     
    Maintainability
    Extract repeated match conditions to enhance maintainability.

    To enhance code maintainability, consider extracting the repeated match conditions into a
    separate variable or function. This will make the code cleaner and reduce duplication,
    especially since the $match stage with conditions on line_items properties is used
    multiple times.

    src/functions/customer/services/payout/aggregation.ts [6-10]

    -{
    +const matchLineItemsCondition = {
       $match: {
         "line_items.properties.customerId": customerId,
         "line_items.current_quantity": 1,
         "line_items.fulfillable_quantity": 0,
         "line_items.fulfillment_status": "fulfilled",
       },
    -}
    +};
    +// Use matchLineItemsCondition in your aggregation pipeline
     
    Extract ShippingModel creation logic into a separate function.

    For better maintainability and readability, consider extracting the logic for creating a
    new ShippingModel instance into a separate function. This can help encapsulate the
    creation logic and make the createShipping function cleaner and more focused on its
    primary responsibility.

    src/library/jest/helpers/shipping.ts [31-37]

    -const shipping = new ShippingModel();
    -shipping.location = filter.location?.toString() || new mongoose.Types.ObjectId();
    -shipping.origin = getOriginObject(filter.origin || {});
    -shipping.destination = {
    -  name: faker.company.buzzPhrase(),
    -  fullAddress: faker.location.streetAddress(),
    +function createNewShippingModel(filter: Partial<Omit<Shipping, "origin">> & { origin: Partial<Location> }): ShippingModel {
    +  const shipping = new ShippingModel();
    +  shipping.location = filter.location?.toString() || new mongoose.Types.ObjectId();
    +  shipping.origin = getOriginObject(filter.origin || {});
    +  shipping.destination = {
    +    name: faker.company.buzzPhrase(),
    +    fullAddress: faker.location.streetAddress(),
    +  };
    +  return shipping;
    +}
    +// Usage within createShipping
    +const shipping = createNewShippingModel(filter);
     
    Best practice
    Use descriptive variable names to improve readability.

    To improve test reliability and readability, consider using a more descriptive variable
    name than dumbData. A name that reflects the purpose or content of the data, such as
    testOrderData, would make the test code clearer to readers and maintainers.

    src/functions/customer/services/payout/balance.spec.ts [32]

    -const dumbData = Order.parse(dummyDataBalance);
    +const testOrderData = Order.parse(dummyDataBalance);
     
    Use MongoDB transactions to ensure data consistency.

    To ensure data consistency and avoid partial writes in case of an error, consider wrapping
    the operations of creating PayoutModel and inserting many PayoutLogModel entries within a
    MongoDB transaction. This way, either all operations succeed, or none do, which is crucial
    for financial transactions.

    src/functions/customer/services/payout/create.ts [66-86]

    -const payout = new PayoutModel({
    -  customerId,
    -  date: new Date(),
    -  amount: totalLineItems + totalShippingAmount,
    -  currencyCode: "DKK",
    -  status: PayoutStatus.PENDING,
    -  payoutType: account.payoutType,
    -  payoutDetails: account.payoutDetails,
    -});
    -await PayoutLogModel.insertMany(
    -  lineItems.map(
    -    (lineItem) =>
    -      ({
    -        customerId,
    -        referenceId: lineItem.line_items.id,
    -        referenceType: PayoutLogReferenceType.LINE_ITEM,
    -        payout: payout._id,
    -      } as PayoutLog)
    -  )
    -);
    +const session = await mongoose.startSession();
    +session.startTransaction();
    +try {
    +  const payout = new PayoutModel({
    +    customerId,
    +    date: new Date(),
    +    amount: totalLineItems + totalShippingAmount,
    +    currencyCode: "DKK",
    +    status: PayoutStatus.PENDING,
    +    payoutType: account.payoutType,
    +    payoutDetails: account.payoutDetails,
    +  });
    +  await PayoutLogModel.insertMany(
    +    lineItems.map(
    +      (lineItem) =>
    +        ({
    +          customerId,
    +          referenceId: lineItem.line_items.id,
    +          referenceType: PayoutLogReferenceType.LINE_ITEM,
    +          payout: payout._id,
    +        } as PayoutLog)
    +    )
    +  );
    +  await session.commitTransaction();
    +} catch (error) {
    +  await session.abortTransaction();
    +  throw error;
    +} finally {
    +  session.endSession();
    +}
     
    Replace random number generation with a fixed or sequential value for customerId.

    Consider using a more deterministic approach for generating customerId when
    props.customerId is not provided. Using faker.number.int() can lead to non-reproducible
    tests which might complicate debugging. A fixed value or a sequence generator could be
    more appropriate.

    src/library/jest/helpers/shipping.ts [15]

    -customerId: props.customerId || faker.number.int({ min: 1, max: 100000 }),
    +customerId: props.customerId || 12345, // Or any other fixed or sequentially generated value
     
    Use toHexString() for clearer conversion of ObjectId to string.

    Ensure that the filter.location?.toString() operation is actually needed and correctly
    converts the location to a string. If filter.location is an ObjectId, it might be more
    appropriate to use filter.location.toHexString() for clarity and to avoid potential issues
    with the default toString() behavior.

    src/library/jest/helpers/shipping.ts [32]

    -shipping.location = filter.location?.toString() || new mongoose.Types.ObjectId();
    +shipping.location = filter.location?.toHexString() || new mongoose.Types.ObjectId();
     
    Validate or sanitize filter.origin before use.

    It's recommended to validate or sanitize the filter.origin object before passing it to
    getOriginObject(). This ensures that only expected properties are included and can prevent
    potential issues related to unexpected data structure or content.

    src/library/jest/helpers/shipping.ts [34]

    -shipping.origin = getOriginObject(filter.origin || {});
    +// Example validation/sanitization function
    +function validateOrigin(origin: Partial<Location>): Partial<Location> {
    +  // Implement validation or sanitization logic here
    +  return origin;
    +}
    +shipping.origin = getOriginObject(validateOrigin(filter.origin) || {});
     
    Enhancement
    Add validation for the filter parameter in createShipping.

    Consider adding error handling or validation for the createShipping function to ensure
    that the input filter meets the expected structure and data types. This can prevent
    runtime errors and ensure that the function behaves as expected.

    src/library/jest/helpers/shipping.ts [28-30]

     export const createShipping = (
       filter: Partial<Omit<Shipping, "origin">> & { origin: Partial<Location> }
     ) => {
    +  // Example validation logic
    +  if (!filter || typeof filter !== 'object') {
    +    throw new Error('Invalid filter provided to createShipping');
    +  }
     

    ✨ Improve tool usage guide:

    Overview:
    The improve tool scans the PR code changes, and automatically generates suggestions for improving the PR code. The tool can be triggered automatically every time a new PR is opened, or can be invoked manually by commenting on a PR.

    • When commenting, to edit configurations related to the improve tool (pr_code_suggestions section), use the following template:
    /improve --pr_code_suggestions.some_config1=... --pr_code_suggestions.some_config2=...
    
    [pr_code_suggestions]
    some_config1=...
    some_config2=...
    

    See the improve usage page for a comprehensive guide on using this tool.

    …e items
    
     - Replace hardcoded collection name with `ShippingModel.collection.name` in `shippingAggregation`.
     - Simplify balance calculation logic in `CustomerPayoutServiceBalance` using `reduce` and filtering for unique shippings.
     - Rename `CustomerPayoutServiceCreateGetLineItemsFulfilled` to `CustomerPayoutServiceGetLineItemsFulfilled` and update references.
     - Insert payout logs for shipping and line items separately, with error handling for insertion failures.
     - Add new `CustomerPayoutServiceGet` to fetch payout details for a customer.
     - Create new test file `get.spec.ts` for `CustomerPayoutServiceGet`.
    @jamalsoueidan
    Copy link
    Owner Author

    @jamalsoueidan
    Copy link
    Owner Author

    /describe

    @github-actions github-actions bot added bug_fix and removed tests labels Mar 31, 2024
    Copy link

    PR Description updated to latest commit (8b12e3c)

     • Implement new API endpoints for managing customer payouts, including getting a single payout, listing payouts with pagination, and retrieving payout balance.
     • Adjust payout balance service to return an object with detailed balance information instead of a single sum.
     • Remove deprecated payout list service and associated tests.
     • Fix incorrect indentation in payout-account get response schema.
     • Implement new customer-payout-log.function.ts for payout log pagination
     • Create CustomerPayoutLogControllerPaginate with schema and handler
     • Fix incorrect import in payout-log/paginate.spec.ts
     • Update CustomerPayoutLogServicePaginate to include type enhancements and correct aggregation logic
    @jamalsoueidan
    Copy link
    Owner Author

    /describe

    Copy link

    PR Description updated to latest commit (a40a296)

    @jamalsoueidan jamalsoueidan merged commit c435d0e into main Mar 31, 2024
    3 checks passed
    @jamalsoueidan jamalsoueidan deleted the payouts-endpoints branch March 31, 2024 22:51
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    Status: Done
    Development

    Successfully merging this pull request may close these issues.

    1 participant