Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: getlago/lago-api
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.32.3
Choose a base ref
...
head repository: getlago/lago-api
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.32.4
Choose a head ref
  • 15 commits
  • 150 files changed
  • 11 contributors

Commits on Aug 11, 2025

  1. misc: Do not create fee if 0 units on current usage (#4076)

    The goal of this PR is to improve performance when doing the backfill of
    daily usages by avoiding creating fees with 0 units on customer usage
    for charge filters.
    
    Here is an example for a single subscription linked to 24 billable
    metrics with 2 filters.
    Only 37 daily usages have been created.
    
    **Before:**
    
    ```
    Benchmark.bm do |x|
      x.report("FillHistoryService:") do
        DailyUsages::FillHistoryService.call!(subscription: s, from_datetime: DateTime.new(2025, 5, 1))
      end
    end
    
    user     system      total        real
    FillHistoryService: 31.097790   1.076836  32.174626 ( 64.291435)
    ```
    Took 64.29s
    
    **After:**
    
    ```
    Benchmark.bm do |x|
      x.report("FillHistoryService:") do
        DailyUsages::FillHistoryService.call!(subscription: s, from_datetime: DateTime.new(2025, 5, 1))
      end
    end
    
    user     system      total        real
    FillHistoryService: 20.107554   0.743215  20.850769 ( 41.683220)
    ```
    Took 41.68s
    rsempe authored Aug 11, 2025
    Configuration menu
    Copy the full SHA
    e0d2049 View commit details
    Browse the repository at this point in the history
  2. misc: Add BillingPerdiodBoundaries (#4121)

    ## Context
    
    In many places of the application, we are defining a `boundaries`
    object, sometimes as an instance of a `Hash`, sometimes as an
    `OpenStruct`. The fields are not always the same and since the
    boundaries are injected in a lot of services, this causes some
    uncertainty when accessing the properties.
    
    ## Description
    
    In an attempt to improve the readability and the reliability of this key
    part of the application, the goal of this PR is to introduce a new
    `BillingPeriodBoundaries` class and to use it everywhere in replacement
    of `Hash` and `OpenStruct`.
    
    It should also improve the memory consumption as OpenStructs are known
    to cause memory issues in Ruby when YJIT is enabled
    vincent-pochet authored Aug 11, 2025
    Configuration menu
    Copy the full SHA
    564a862 View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    7f9ed0b View commit details
    Browse the repository at this point in the history
  4. feat(projected-usage): Create a new endpoint for the projected usage …

    …calculation (#4124)
    
    ## Context
    
    The `current_usage` endpoint is frequently called across the
    application. Adding the projected usage calculation was causing
    significant memory spikes due to the high request volume, impacting
    application performance.
    
    By moving the expensive calculation to a dedicated endpoint, we ensure
    that fetching basic usage remains fast and stable, while still providing
    the projection data when it's explicitly needed. This resolves the
    memory issues and improves overall stability.
    
    ## Description
    
    Creates a new endpoint, `GET
    /customers/:external_customer_id/projected_usage`, to handle the
    computationally intensive projected usage calculation.
    
    Reverts the existing `/customers/:external_customer_id/current_usage`
    endpoint to its original, lightweight state by removing the projection
    logic.
    murparreira authored Aug 11, 2025
    Configuration menu
    Copy the full SHA
    2d683f8 View commit details
    Browse the repository at this point in the history

Commits on Aug 12, 2025

  1. feat(one-off-invoice): Add billing period to one-off invoices (#4119)

    ## Context
    
    Currently fees on one-off invoices does not contain billing period
    
    ## Description
    
    As part of the `quotes` feature, the decision is to add billing period
    on one-off invoice. This information would be consumed by analytics
    since it would allow splitting revenue across the billing interval
    
    ---------
    
    Co-authored-by: Alexandre Monjol <alexandre.monjol@gmail.com>
    lovrocolic and ansmonjol authored Aug 12, 2025
    Configuration menu
    Copy the full SHA
    271fb54 View commit details
    Browse the repository at this point in the history
  2. fix(netsuite): Fix invoice payload - add item_source (#4120)

    ## Description
    
    We need to add a new field for NetSuite invoice creation: `item_source`
    ivannovosad authored Aug 12, 2025
    Configuration menu
    Copy the full SHA
    8c4a710 View commit details
    Browse the repository at this point in the history
  3. fix/allow query subscriptions with plan attributes (#4129)

    ## Problem
    You can't filter by any plan attribute and have a search term. 
    
    ## Steps to reproduce
    Add a filter to plan/subscription and a search term. 
    ```SubscriptionsQuery.call(organization:, filters: {overriden: true}, search_term: "Mario")```
    
    This would produce this query
    ```
    Subscription Count (0.5ms) SELECT COUNT(*) FROM (SELECT 1 AS one FROM
    "subscriptions" INNER JOIN "customers" ON "customers"."id" =
    "subscriptions"."customer_id" INNER JOIN "plans" "plan" ON "plan"."id" =
    "subscriptions"."plan_id" WHERE "subscriptions"."organization_id" = $1
    AND ((((((((("subscriptions"."id"::varchar ILIKE '%Mario%' OR
    "subscriptions"."name" ILIKE '%Mario%') OR "subscriptions"."external_id"
    ILIKE '%Mario%') OR "plans"."name" ILIKE '%Mario%') OR "plans"."code"
    ILIKE '%Mario%') OR "customers"."name" ILIKE '%Mario%') OR
    "customers"."firstname" ILIKE '%Mario%') OR "customers"."lastname" ILIKE
    '%Mario%') OR "customers"."external_id" ILIKE '%Mario%') OR
    "customers"."email" ILIKE '%Mario%') AND "plan"."parent_id" IS NULL
    LIMIT $2 OFFSET $3) subquery_for_count [["organization_id",
    "034de852-b25c-41c5-9f58-a8f07bdcd2bd"], ["LIMIT", 25], ["OFFSET", 0]]
    ```
    
    but fails with 
    ```
    (lago-api):8:in '<main>': PG::UndefinedTable: ERROR: invalid reference
    to FROM-clause entry for table "plans" (ActiveRecord::StatementInvalid)
    LINE 1: ..."subscriptions"."external_id" ILIKE '%Mario%') OR
    "plans"."n...
                                                                 ^
    HINT:  Perhaps you meant to reference the table alias "plan".
    ```
    
    Ramsack calls the table `plans` as `plans` and in our query, we are calling `plan`. 
    
    ## Fix
    Call the `plans` table as `plans` just like Ramsack, without an alias.
    ```
    SELECT COUNT(*) FROM (SELECT 1 AS one FROM "subscriptions" INNER JOIN
    "customers" ON "customers"."id" = "subscriptions"."customer_id" INNER
    JOIN "plans" ON "plans"."id" = "subscriptions"."plan_id" WHERE
    "subscriptions"."organization_id" = $1 AND
    ((((((((("subscriptions"."id"::varchar ILIKE '%Mario%' OR
    "subscriptions"."name" ILIKE '%Mario%') OR "subscriptions"."external_id"
    ILIKE '%Mario%') OR "plans"."name" ILIKE '%Mario%') OR "plans"."code"
    ILIKE '%Mario%') OR "customers"."name" ILIKE '%Mario%') OR
    "customers"."firstname" ILIKE '%Mario%') OR "customers"."lastname" ILIKE
    '%Mario%') OR "customers"."external_id" ILIKE '%Mario%') OR
    "customers"."email" ILIKE '%Mario%') AND "plans"."parent_id" IS NULL
    LIMIT $2 OFFSET $3) subquery_for_count [["organization_id",
    "034de852-b25c-41c5-9f58-a8f07bdcd2bd"], ["LIMIT", 25], ["OFFSET", 0]]
    ```
    mariohd authored Aug 12, 2025
    Configuration menu
    Copy the full SHA
    5e234e5 View commit details
    Browse the repository at this point in the history
  4. feat(audit_logs): Let the organization query unlimited audit logs (#4131

    )
    
    ## Problem
    An organization can't query ActivityLogs older than 30 days. 
    The number 30 days is hardcoded in the code. 
    
    ## Fix
    Add an attribute on `Organization` called `audit_logs_period` and use
    this as the period allowed to query the Activity Logs. When `nil`, it
    should not limit query.
    mariohd authored Aug 12, 2025
    Configuration menu
    Copy the full SHA
    355bfbe View commit details
    Browse the repository at this point in the history
  5. misc(event): remove unique validation (#4133)

    ## Context
    
    This PR intend to improve the performance when creating an event using
    the `POST /api/v1/events`.
    
    The event model has a uniqueness validation on the transaction_id field.
    Rails is performing a database query to validate this uniquess and it
    appears to be slow...
    
    ## Description
    
    Since we already have a unique index in place in the database, this PR
    removes the validation and adds the logic to catch the Postgres error.
    Some load testing have been conducted with this approach and it cuts the
    response time by a large factor, increasing the number of events/sec
    that could be received by the API
    vincent-pochet authored Aug 12, 2025
    Configuration menu
    Copy the full SHA
    f58345e View commit details
    Browse the repository at this point in the history
  6. fix(weighted-sum): Clickhouse query (#4134)

    Error: Different expressions with the same alias
    difference:\ntoDecimal128(25., 26) AS difference\nand\ntoDecimal128(15.,
    26) AS difference\n: While processing toDecimal128(25., 26) AS
    difference.
    rsempe authored Aug 12, 2025
    Configuration menu
    Copy the full SHA
    28f4771 View commit details
    Browse the repository at this point in the history

Commits on Aug 13, 2025

  1. Configuration menu
    Copy the full SHA
    8fbf697 View commit details
    Browse the repository at this point in the history
  2. Feat(fixed_charges): Add GraphQL types, update Plan resolver and crea…

    …te mutation (#4126)
    
    ## Roadmap Task
    
    👉
    https://getlago.canny.io/feature-requests/p/allow-add-ons-to-be-added-to-subscription-invoices
    
    👉
    https://getlago.canny.io/feature-requests/p/define-quantities-for-plan-charges
    
     ## Context
    
     What is the current situation?
    
     **Option 1:** User has to create a one off invoice alongside the
     subscription, it will create 2 different invoices.
    
     **Option 2:** User can add a recurring billable metric and use event to
     have this fee invoice on subscription renewal, but it won’t appear on
     the first billing subscription.
    
     What problem are we trying to solve?
    
     At subscription creation or afterward, there is no clear way to invoice
     a fixed fee that is not tied to events, aside from the subscription fee
     itself. This fee could be either a one-time charge or a recurring one.
    
     ## Description
    
    Update Plans::Create mutation and Plan resolver to include fixed charges
    data,
      also, adds all required graphql types.
    ancorcruz authored Aug 13, 2025
    Configuration menu
    Copy the full SHA
    c243abe View commit details
    Browse the repository at this point in the history
  3. Feat(fixed charges 6): update services (#4138)

    ## Context
    
    We need a service to update fixed charge and cascade-update. When
    updating a fixed charge, we can't change `pay_in_advance` and `prorated`
    `display_name` can only be changed in parent fixed_charge (not updated
    while cascade)
    `charge_model` can only be updated if plan is not attached to any
    subscription
    `properties` can be updated while cascading only if before update
    current fixed_charge and the child had matching properties
    `taxes` can be changed only for parent fixed_charge without attached
    subscription
    
    ## Description
    
    - added `FixedCharges::UpdateService`
    annvelents authored Aug 13, 2025
    Configuration menu
    Copy the full SHA
    68d2fab View commit details
    Browse the repository at this point in the history
  4. feat(customers-filters): Add active_subscriptions_from and active_sub… (

    #4122)
    
    ## Problem
    List the customers that has N active subscriptions.
    ## Fix
    Adding the `active_subscriptions_count_from` and
    `active_subscriptions_count_to` to `CustomersResolver`.
    This will be used to filter the active subscriptions for the customers.
    mariohd authored Aug 13, 2025
    Configuration menu
    Copy the full SHA
    3f73fb1 View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    4995a54 View commit details
    Browse the repository at this point in the history
Loading