Commit Graph

30 Commits

Author SHA1 Message Date
Paul Derscheid 1f45a43f1d
Bug 41898: (QA follow-up) Skip clash detection when collecting a booking
Transitioning a booking to 'issued' no longer skipped clash detection,
and Item::check_booking treats any live checkout on the item as a
clash. Switching an on-site checkout of a booked item to a regular
checkout (SwitchOnSiteCheckouts) therefore crashed AddIssue with an
unhandled Koha::Exceptions::Booking::Clash; collection could fail the
same way whenever the biblio's bookable item pool had shrunk since the
booking was placed.

- short-circuit no-op stores before validation; circulation issues
  redundant status writes that must not re-trigger the checks
- rename _is_final_status_transition to _skip_clash_detection and also
  skip when transitioning to 'issued' from an active status, as long
  as the booked period and item are unchanged
- keep validating period/item changes and reactivations of terminal
  bookings
- cover the on-site switch in Circulation.t and the store() semantics
  in Booking.t

Test plan:
1. Enable OnSiteCheckouts and SwitchOnSiteCheckouts
2. Place a booking starting today for a patron
3. Check the booked item out to that patron from Circulation > Check
   out with 'On-site checkout' ticked. Do NOT use the bookings page's
   'Transform to checkout' button: it submits a fixed field set that
   does not carry the on-site flag (Bug 36789), so the checkout would
   silently be a regular one and step 4 could not reproduce the switch
4. The booking shows 'Issued'. Scan the same barcode for the same
   patron again to switch the on-site checkout to a regular one; this
   crashed with Koha::Exceptions::Booking::Clash before the patch and
   now succeeds with the booking still 'Issued'
5. prove t/db_dependent/Koha/Booking.t t/db_dependent/Circulation.t

Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-07-27 15:53:38 +00:00
Martin Renvoize c7673a9d6a
Bug 41898: Introduce 'issued' status and update booking display/filtering
Implements a 4-state booking lifecycle: new → issued (on checkout) →
completed (on return), plus cancelled at any point.

Backend changes:
- AddIssue sets booking status to 'issued' (was incorrectly 'completed')
- AddReturn transitions 'issued' → 'completed' via booking_id on the issue
- filter_by_active updated to status-based: status IN ('new', 'issued');
  previously it filtered by date range — active/inactive now reflect booking
  lifecycle rather than the current date relative to start/end dates
- _is_final_status_transition reverted to only skip clash detection for
  terminal statuses 'cancelled' and 'completed'; 'issued' is active and does
  not bypass clash detection
- GET /api/v1/bookings no longer pre-filters to active bookings server-side;
  callers must supply an explicit status filter if they need active-only

Display changes:
- Patron bookings tab: replaces the date-based expired/active toggle with
  per-status filters (completed, cancelled) using the AdditionalFilters
  framework; active bookings (new/issued) are shown by default
- Biblio bookings list: same status-based filters; removes the date-based
  expired filter that was still present
- Status column is always visible on both views (was previously hidden on
  the patron tab unless expired bookings were shown)
- Status badges: new=bg-success, issued=bg-info, completed/cancelled=bg-secondary
- Timeline isActive check corrected to ['new','issued']
- patron-detail-tabs.inc: rename expired_bookings_count → closed_bookings_count
  to reflect status-based (not date-based) counting
- Filter button colour fixed to use $link-color so both views are consistent

Test plan:
1. Enable the EnableBookings system preference.
2. Create a biblio with at least one bookable item.
3. Place a booking for a patron via the biblio's Bookings tab.
   - The booking should appear with status badge "New" (green).
4. Check out the booked item to that patron (Circulation → Check out).
   - Reload the Bookings tab; the booking should now show "Issued" (blue).
5. Return the item (Circulation → Check in).
   - Reload the Bookings tab; the booking should now show "Completed" (grey).
6. Place a second booking and cancel it from the Bookings tab Actions menu.
   - The booking should show "Cancelled" (grey), with the reason if provided.
7. On the biblio Bookings tab:
   - Completed and cancelled bookings are hidden by default.
   - Clicking "Include completed" shows completed bookings.
   - Clicking "Include cancelled" shows cancelled bookings.
   - Both can be toggled independently.
   - The Status column is always visible.
8. Navigate to the patron's detail page → Bookings tab.
   - Active bookings (new/issued) are shown by default.
   - Completed and cancelled can be toggled independently using the same
     filter buttons.
   - The Status column is always visible.
9. Confirm via the REST API that GET /api/v1/bookings (no filters) returns
   bookings of all statuses, not just active ones.

Sponsored-by: OpenFifth <https://openfifth.co.uk/>
Sponsored-by: Westminster City Council <https://www.westminster.gov.uk/>
Signed-off-by: Hannah Dunne-Howrie <hdunne-howrie@westminster.gov.uk>
Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
2026-07-27 15:53:33 +00:00
Paul Derscheid ee667d3ddf
Bug 41887: Skip clash detection on terminal status transition
- Booking::store runs item-level and biblio-level clash
  detection unconditionally on every call
- During checkout, C4::Circulation sets the booking status to
  'completed' and calls ->store(), which triggers clash checks
- Combined with false positives from Biblio::check_booking
  (e.g. checkouts on non-bookable sibling items inflating the
  unavailable count), this throws
  Koha::Exceptions::Booking::Clash resulting in a 500 error
- Running clash detection on a terminal transition is
  unnecessary regardless; skip it for cancelled/completed
- Add _is_final_status_transition() helper that inspects the
  dirty columns to detect completed/cancelled transitions
- Guard both clash detection blocks with the new helper

To test:
1. Have a biblio with two items: one bookable, one not
   (bookable = 0).
2. Create a booking on the bookable item.
3. Check out the non-bookable item to a patron.
4. Check out the bookable item to the booking patron (this
   triggers the completed transition via C4::Circulation).
5. Without the patch: 500 error from
   Koha::Exceptions::Booking::Clash.
6. Apply the patch.
7. Repeat steps 2-4.
8. Verify the checkout succeeds and the booking transitions
   to completed.
9. Run: prove t/db_dependent/Koha/Booking.t
   and confirm the new subtest "store() skips clash
   detection on terminal status transition" passes.

Sponsored-by: Büchereizentrale Schleswig-Holstein <https://www.bz-sh.de/>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-02-26 09:04:22 -07:00
Martin Renvoize c7fa646929
Bug 40134: Implement optimal item selection for 'any item' bookings
This patch implements an algorithm for selecting the item that would
leave the largest gap after the proposed booking to maximize the
opportunity for future bookings.

Key Changes:

Koha::Booking:
- Added set_itemtype_filter() method for transient itemtype parameter
- Added _select_optimal_item() method using single aggregated query
  * Groups bookings by item_id with MIN(start_date)
  * Selects items with no future bookings (optimal)
  * Among items with bookings, selects one with latest next booking
  * O(1) complexity - single database query with GROUP BY
- Updated _assign_item_for_booking() to use optimal selection
  * Filters by itemtype when itemtype_id is provided
  * Replaces previous random selection (RAND())

API Changes:
- Added itemtype_id parameter support to add() endpoint
- Added itemtype_id parameter support to update() endpoint
- Validates exactly one of item_id or itemtype_id is provided
- itemtype_id is transient - not persisted to database
- Extracted and applied via set_itemtype_filter() before store()

Architecture:
- itemtype_id is NOT a database column (transient only)
- Used as selection criterion, then discarded

Test plan:
1. Apply patch and restart services
2. Create "any item" booking via staff interface
3. Verify item with longest future availability is selected
4. Test via API with itemtype_id parameter
5. Verify itemtype_id is not persisted to database
6. Run t/db_dependent/Koha/Booking.t
7. Run t/db_dependent/api/v1/bookings.t

Signed-off-by: Kristi Krueger <kkrueger@cuyahogalibrary.org>
Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2026-02-10 08:50:56 -07:00
Tomas Cohen Arazi 1873d97c07
Bug 40163: Fix several http addresses in the code docs
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Brendan Lawlor <blawlor@clamsnet.org>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-23 16:21:29 -06:00
Paul Derscheid c0f191b79c
Bug 40665: Link checkouts to bookings
This patch adds a booking_id field to the issues and old_issues tables
to create a linkage between checkouts and the bookings that generated
them. When a patron with a booking checks out the reserved item, the
checkout is linked to their booking and the booking status is updated
to 'completed'.

The booking_id is preserved during renewals and when checkouts are
moved to old_issues upon return.

Database changes:
- Add booking_id column to issues and old_issues tables
- Add foreign key constraints to maintain referential integrity

Test plan:
1. Apply the database update
2. Restart services
3. Create a booking for a patron
4. When the patron checks out the booked item:
 a. Verify the checkout links to the booking (booking_id is set)
 b. Verify the booking status changes to 'completed'
5. Renew the checkout
 a. Verify the booking_id is preserved after renewal
 b. Check the database: SELECT booking_id FROM issues WHERE issue_id = X
6. Return the item
 a. Verify the checkout moves to old_issues
 b. Verify the booking_id is preserved in old_issues
7. Test the new Koha::Booking methods:
 a. For a booking with a checkout, verify $booking->checkout returns
    the correct Koha::Checkout object
 b. For a booking with an old checkout, verify $booking->old_checkout
    returns the correct Koha::Old::Checkout object
8. Test the API:
 a. Verify checkout endpoints include booking_id in responses
 b. Verify the booking relationship can be embedded using
    x-koha-embed: booking
9. Run the test suite:
 prove t/db_dependent/Circulation.t
 prove t/db_dependent/Koha/Booking.t
 prove t/db_dependent/Koha/Checkout.t

NOTE: I also thought about the inverse: linking to a checkout from the
booking, but as Koha is a circulation centric system, this approach makes
more sense in my opinion. I also thought about bidirectional linking via
FKs but that is too much maintenance overhead (and potential error source)
that we don't need. The inverse lookups should still be performant through
the FKs.

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2025-09-05 15:10:36 -06:00
Koha Development Team d659526b5a
Bug 38664: Tidy the whole codebase
This commit is generated using:
  % perl misc/devel/tidy.pl
*within* ktd, to get the same version of perltidy than what will be used
by our CI (currently v20230309).

Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2025-02-11 14:58:24 +01:00
Martin Renvoize 9cfb92c206
Bug 38175: (follow-up) Quiet warnings in tests
We weren't passing the required data into the FKConstraint exception,
this patch passes biblio_id and value as required.
2024-11-04 13:12:12 +00:00
Martin Renvoize 43e50297bc
Bug 38175: Handle status in item auto-assignment for bookings
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-10-24 18:27:26 +02:00
Martin Renvoize e8185e14cc
Bug 38175: (QA follow-up) DRY out PATCH handling
We were repeating some code for the PATCH endpoint instead of using the
existing update handling code.  This lead to two issues:

1) We weren't catching status updates on standard updates, only the
   patch.
2) We were limiting the PATCH endpoint to just status updates when it
   could happily be used for other fields too.

This patch removes the introduction of the 'edit' method from both the
REST controller and the corresponding object and moves the logic into
the store method of the object where it's easily testable.

We also DRY out the notice sending code a little for re-use.

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-10-24 18:27:24 +02:00
Martin Renvoize 35136c234d
Bug 38175: (QA follow-up) Remove superflous method
If all we're doing is calling SUPER, then we don't need to wrap ;P

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-10-24 18:27:23 +02:00
Paul Derscheid 36c5a1c011
Bug 38175: (follow-up) Refactor staff interface additions to vanilla JS; adjust modules, controllers for coding guidelines and consistency
In the spirit of the current movement for more modern JS, the refactor tries to limit jQuery usage.

Test plan:
    1) Create a booking on a bookable item
    2) Cancel it and see that it's simply deleted
    3) Apply the patch and run “restart_all”.
    4) Repeat the same cancel operation and see that it's still there, albeit with a different appearance.
    5) Try the filters in the table

Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-10-24 18:27:23 +02:00
Thibaud Guillot 7eca5a8adc
Bug 38175: Improve Bookings feature with status
With the integration of the new status column for bookings, it would be preferable to keep the booking in database and simply change its status to 'cancel' when you cancel it via the action button or the timeline.

So I've added partial updating via the API with a new PATCH method to partially edit a booking. It is currently active for status changes.
Graphically, this translates into the disappearance of the action buttons if the booking has already been canceled, although it remains visible in the table and timeline (the style is a proposal for the moment, intended simply to graphically differentiate a canceled booking from others).

I've also added a filter to the filter_by_active method to exclude cancelled bookings.

Test plan:
1) Create a booking on a bookable item
2) Cancel it and see that it's simply deleted
3) Apply the patch and run “restart_all”.
4) Repeat the same cancel operation and see that it's still there, albeit with a different appearance.
5) Try the filters in the table

Sponsored by: BibLibre
Signed-off-by: Paul Derscheid <paul.derscheid@lmscloud.de>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-10-24 18:27:21 +02:00
Paul Derscheid 0146baf294
Bug 37803: Add patron notification when a new booking has been created successfully
To test:
1) Apply the patch
2) Include the sample notice, e.g. run 'reset_all' on ktd
3) Create a booking
4) Look into the borrower notifications
5) Confirm the notice has been generated
6) Run t/db_dependent/Koha/Booking.t

Signed-off-by: LEBSimonsen <simonsen@bz-sh.de>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Sponsored-by: Büchereizentrale Schleswig-Holstein <https://www.bz-sh.de/>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-10-24 18:27:21 +02:00
Martin Renvoize ffd60727f1
Bug 37204: (QA follow-up) Consistently pick notice library
We should use the notice from the library that initiated the action that
triggered the notice. This should be available to us always in the
userenv.

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Sponsored-by: Büchereizentrale Schleswig-Holstein <https://www.bz-sh.de/>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-10-24 18:27:20 +02:00
Martin Renvoize db8531c58b
Bug 37204: (QA follow-up) Pass old_booking into GetPreparedLetter
Thinking about the future, some libraries may wish to use the
old_booking object details in their notice so I opt to pass it into
GetPreparedLetter here to support that.

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Sponsored-by: Büchereizentrale Schleswig-Holstein <https://www.bz-sh.de/>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-10-24 18:27:20 +02:00
Paul Derscheid d2c8bbd7cb
Bug 37204: Add a booking has changed notice to update a patron should a booking be updated
This is a first draft. When reading your initial statement again I'm asking myself whether
a changed itemnumber is relevant to the patron.
The way I see it, the relevant fields are:
- pickup_library_id
- start_date
- end_date

But maybe I'm not seeing it.

To test:
1) Apply the patch
2) Make an item bookable
3) Add a booking for a given patron
4) Check the patron notices tab, should not contain any notices
5) Change either start date, end date or pickup library and save
6) Check the patron notices tab, should contain a notice with the updated details
7) Run the tests under t/db_dependent/Koha/Booking.t
8) Sign off

Signed-off-by: LEBSimonsen <simonsen@bz-sh.de>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Sponsored-by: Büchereizentrale Schleswig-Holstein <https://www.bz-sh.de/>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-10-24 18:27:19 +02:00
Paul Derscheid e75c1ac012
Bug 37592: (QA follow-up) Change created_on, updated_on to creation_date, modification_date
It makes sense not to introduce mapping code if there's no reason for it.
Accordingly the the columns are now of type DATETIME instead.

Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-09-16 13:47:11 +02:00
Martin Renvoize b884de71ce
Bug 37592: (QA follow-up) Add API mapping and definition
Sticking to API guidelines, this adds the creation_date and
modification_date fields to the api definitions and the required
to_api_mappings for those fields to be properly populated.

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-09-16 13:47:10 +02:00
Martin Renvoize a3a1d7e253
Bug 36915: (QA follow-up) Passing less to encourage traversal
I generally push for contextual use of accessors in TT notices and try
to reduce extra lookups.

In this case we can access the pickup library branchname directly using
the pickup_library relation available to us in the booking object we
pass.

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-08-27 12:14:20 +02:00
Paul Derscheid 714ebfb66c
Bug 36915: (follow-up) Include branchname in sample notice
Signed-off-by: Owen Leonard <oleonard@myacpl.org>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-08-27 12:14:19 +02:00
Martin Renvoize 3db1985149
Bug 36915: (follow-up) Pass object to GetPreparedLetter
This patch updates the logic to pass the object to be deleted through to
GetPreparedLetter.

This way, as we add fields and accessors to the object in the future,
they will automatically become available to the notices.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Owen Leonard <oleonard@myacpl.org>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-08-27 12:14:17 +02:00
Thibaud Guillot 0ba56480a5
Bug 36915: Send email notification when a booking is cancelled
When a booking is cancelled, patron received an email based on specific
letter.

Test plan:

1) Create a letter with code "BOOKING_CANCELLATION" on "Notices and
   slips" tool.
2) Add booking or go on item already booked in advance.
3) Cancel it
4) Verify in message_queue table directly or go on patron page and click
   on "Notices" tab section.

Sponsored by: Association de Gestion des Œuvres Sociales d'Inria (AGOS)
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Owen Leonard <oleonard@myacpl.org>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-08-27 12:14:17 +02:00
Martin Renvoize dadabbd924
Bug 36120: Add pickup_library support to bookings API
Sponsored-by: Cuyahoga County Public Library
Signed-off-by: Lisette Scheer <lisette.scheer@bywatersolutions.com>
Signed-off-by: Kristi Krueger <kkrueger@cuyahogalibrary.org>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-05-03 16:02:46 +02:00
Martin Renvoize d0981505ba
Bug 35248: Refactor - Move assign_item_for_booking
This routine really belongs inside Koha::Booking rather than
Koha::Biblio. This patch moves it there, renames with _ to highlight
it's private nature.

Test plan
1) Confirm that t/db_dependant/Koha/Booking.t still passes, specifically
   the 'store' test.

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-03-15 09:38:50 +01:00
Martin Renvoize 89fc242e97
Bug 35248: Add tests for Koha::Booking->store
This patch adds tests for the Koha::Booking->store method.

Test plan
1) Run t/db_dependent/Koha/Booking.t and confirm they all pass

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-03-15 09:38:49 +01:00
Martin Renvoize b351ab12de
Bug 35248: Remove Koha::Booking->intersects
Another method left behind from an earlier iteration.. not actually
called anywhere in the final submission in Koha.

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
2024-03-15 09:38:46 +01:00
Tomas Cohen Arazi 6b7e493448
Bug 29002: Tidy
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
2023-11-03 12:04:30 -03:00
Martin Renvoize 2c6d57c254
Bug 29002: Assign item at time of booking
This patch updates the logic to ensure we always assign an item at the
point of booking instead of assuming we can assign the item at fulfilment time.

This makes the logic significantly simpler on the client when trying to
calculate available dates.

Test plan
1) Attempt to create a new booking using the 'Any item' option in the
   modal
2) Note that upon placing your booking you are assigned an item for that
   booking.

NOTE: We add a FIXME to the client code to highlight something to test
when/if someone decides to have another try and moving the item
assigment to just in time as aposed to up front.

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Janet McGowan <janet.mcgowan@ptfs-europe.com>
Signed-off-by: Caroline Cyr La Rose <caroline.cyr-la-rose@inlibro.com>
Signed-off-by: Laurence Rault <laurence.rault@biblibre.com>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
2023-11-03 12:04:19 -03:00
Martin Renvoize e8d5219547
Bug 29002: Add bookings objects and API classes
This patch adds new Koha::Object based classes for bookings logic and
adds API controllers to expose the new bookings data via the REST API's.

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Janet McGowan <janet.mcgowan@ptfs-europe.com>
Signed-off-by: Caroline Cyr La Rose <caroline.cyr-la-rose@inlibro.com>
Signed-off-by: Laurence Rault <laurence.rault@biblibre.com>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
2023-11-03 12:04:07 -03:00