Skip to content

Voucher improvements#43

Merged
joamag merged 6 commits intomasterfrom
feat/voucher-improvements
Jun 16, 2025
Merged

Voucher improvements#43
joamag merged 6 commits intomasterfrom
feat/voucher-improvements

Conversation

@joamag
Copy link
Copy Markdown
Contributor

@joamag joamag commented Jun 16, 2025

This pull request introduces significant enhancements to the voucher system in the budy application. The changes include extending voucher functionality with new attributes, operations, and validations, as well as introducing a new VoucherUse model to track voucher usage. These updates aim to provide more flexibility and control over voucher creation, management, and usage.

Enhancements to voucher functionality:

  • Expanded voucher attributes and operations:

    • Added new fields such as usage_limit, start, expiration, and meta to the Voucher model to support more complex voucher configurations. These attributes allow setting limits, validity periods, and metadata for vouchers. (src/budy/models/voucher.py, [1] [2] [3] [4] [5]
    • Updated methods like create_value_s, create_value_multiple_s, create_percentage_s, and create_percentage_multiple_s to incorporate the new attributes. (src/budy/models/voucher.py, [1] [2] [3]
  • New API endpoints for voucher usage:

    • Introduced use and disuse endpoints to manage voucher usage. The use endpoint supports saving usage data with optional justification, while the disuse endpoint reverses voucher usage. (src/budy/controllers/api/voucher.py, src/budy/controllers/api/voucher.pyL82-R115)

Introduction of VoucherUse model:

  • Tracking voucher usage:
    • Added a new VoucherUse model to record detailed information about voucher usage, including amount, justification, and references to the associated voucher and account. (src/budy/models/voucher_use.py, src/budy/models/voucher_use.pyR1-R96)
    • Updated the use_s method in Voucher to optionally save usage details in the VoucherUse model. (src/budy/models/voucher.py, src/budy/models/voucher.pyL248-R346)

Codebase organization:

  • Model imports:
    • Added the VoucherUse model to the src/budy/models/__init__.py file for proper module integration. (src/budy/models/__init__.py, src/budy/models/init.pyR87)

Summary by CodeRabbit

  • New Features

    • Added support for creating vouchers with additional attributes such as usage limit, start date, expiration date, and metadata.
    • Introduced endpoints to use and disuse vouchers, including the ability to log voucher usage with justification.
    • Voucher usage is now tracked and can be associated with a justification and account.
  • Improvements

    • Enhanced voucher retrieval and creation to use a flexible key instead of a numeric ID.
    • Added detailed metadata to voucher fields for improved clarity.

joamag added 2 commits June 16, 2025 23:40
Update key parameter naming, and add observations to voucher fields
…n fields

Added new parameters for usage limit, start, and expiration to voucher creation methods in both the API controller and model. Updated relevant methods to handle these new fields
@joamag joamag requested a review from Copilot June 16, 2025 22:53
@joamag joamag self-assigned this Jun 16, 2025
@joamag joamag added the enhancement New feature or request label Jun 16, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 16, 2025

Warning

Rate limit exceeded

@joamag has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 13 minutes and 48 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 2afabeb and 0a90c38.

📒 Files selected for processing (4)
  • src/budy/controllers/api/voucher.py (3 hunks)
  • src/budy/models/voucher.py (6 hunks)
  • src/budy/models/voucher_use.py (1 hunks)
  • src/budy/test/voucher.py (1 hunks)

Walkthrough

The changes introduce enhanced voucher management features. The voucher retrieval endpoint now uses a string key instead of an integer ID. Voucher creation methods support additional parameters such as usage limits, start and expiration dates, and metadata. New endpoints allow for using and disusing vouchers, with usage logging implemented via a new VoucherUse model.

Changes

File(s) Change Summary
src/budy/controllers/api/voucher.py Updated endpoints to use string key, expanded voucher creation parameters, added endpoints for using/disusing vouchers.
src/budy/models/voucher.py Added metadata to fields, expanded creation methods with new parameters, implemented usage logging with justification.
src/budy/models/voucher_use.py Introduced new VoucherUse model to log voucher usage with justification and references to voucher/account.
src/budy/models/__init__.py Imported VoucherUse model for package-wide availability.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant APIController as VoucherAPIController
    participant VoucherModel as Voucher
    participant VoucherUseModel as VoucherUse

    Client->>APIController: POST /api/vouchers/<key>/use (amount, currency, justification, save_use)
    APIController->>VoucherModel: use_s(amount, currency, justification, save_use)
    alt save_use is True
        VoucherModel->>VoucherUseModel: create usage record (amount, justification, voucher, account)
    end
    VoucherModel-->>APIController: updated voucher, usage record (if any)
    APIController-->>Client: JSON response with voucher and usage info

    Client->>APIController: POST /api/vouchers/<key>/disuse
    APIController->>VoucherModel: disuse_s()
    VoucherModel-->>APIController: updated voucher
    APIController-->>Client: JSON response with updated voucher
Loading

Poem

A voucher’s tale, now richer told,
With keys and logs and metadata bold.
Use and disuse, tracked with care,
Justifications floating in digital air.
New models hop in, usage to chart—
A rabbit’s delight, efficiency’s art!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR enhances the voucher system by adding richer configuration and usage tracking.

  • Extended Voucher model with usage_limit, start, expiration, and meta attributes and updated the factory operations to accept them.
  • Introduced the VoucherUse model to record usage details and augmented use_s/disuse_s to persist usage.
  • Updated API routes to look up vouchers by key and added /use and /disuse endpoints.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/budy/models/voucher_use.py Added VoucherUse model for recording voucher usage
src/budy/models/voucher.py Extended Voucher with new fields/operations and updated use_s/disuse_s
src/budy/models/init.py Registered VoucherUse in the models package
src/budy/controllers/api/voucher.py Changed voucher lookup to key and added /use//disuse API endpoints
Comments suppressed due to low confidence (1)

src/budy/controllers/api/voucher.py:54

  • Change the route parameter from <int:key> to <str:key> (or omit the type) so voucher keys (which are strings) can be matched correctly.
@appier.route("/api/vouchers/<int:key>", "GET", json=True)

Comment thread src/budy/models/voucher_use.py Outdated
Comment on lines +60 to +61
observations="""Justification or reason for the usage of the voucher,m
may contain external ID references""",
Copy link

Copilot AI Jun 16, 2025

Choose a reason for hiding this comment

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

Fix the typo in the observations comment: change voucher,m to voucher, may (or remove the comma) to correct the spacing.

Suggested change
observations="""Justification or reason for the usage of the voucher,m
may contain external ID references""",
observations="""Justification or reason for the usage of the voucher, may
contain external ID references""",

Copilot uses AI. Check for mistakes.
self.used = False

def use_s(self, amount, currency=None):
def use_s(self, amount, currency=None, justification=None, save_use=True):
Copy link

Copilot AI Jun 16, 2025

Choose a reason for hiding this comment

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

The use_s method accepts a currency parameter but later passes it to VoucherUse, which does not define a currency field, resulting in an unexpected keyword argument error.

Copilot uses AI. Check for mistakes.
Comment on lines +331 to +346
def use_s(self, amount, currency=None, justification=None, save_use=True):
amount_l = self.to_local(amount, currency)
appier.verify(self.is_valid(amount=amount, currency=currency))
if self.is_value and not self.unlimited:
self.used_amount += commons.Decimal(amount_l)
self.usage_count += 1
self.save()
if save_use:
voucher_use_ = voucher_use.VoucherUse(
voucher=self,
amount=amount,
currency=currency,
justification=justification,
)
voucher_use_.save()
return voucher_use_
Copy link

Copilot AI Jun 16, 2025

Choose a reason for hiding this comment

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

Remove or replace the currency argument when creating VoucherUse, and set usage_type (e.g., VoucherUse.USAGE_TYPE_S['value'] or ['percentage']) to record the usage type correctly.

Suggested change
def use_s(self, amount, currency=None, justification=None, save_use=True):
amount_l = self.to_local(amount, currency)
appier.verify(self.is_valid(amount=amount, currency=currency))
if self.is_value and not self.unlimited:
self.used_amount += commons.Decimal(amount_l)
self.usage_count += 1
self.save()
if save_use:
voucher_use_ = voucher_use.VoucherUse(
voucher=self,
amount=amount,
currency=currency,
justification=justification,
)
voucher_use_.save()
return voucher_use_
def use_s(self, amount, justification=None, save_use=True):
amount_l = self.to_local(amount, self.currency)
appier.verify(self.is_valid(amount=amount, currency=self.currency))
if self.is_value and not self.unlimited:
self.used_amount += commons.Decimal(amount_l)
self.usage_count += 1
self.save()
if save_use:
usage_type = (
voucher_use.VoucherUse.USAGE_TYPE_S["value"]
if self.is_value
else voucher_use.VoucherUse.USAGE_TYPE_S["percentage"]
)
voucher_use_ = voucher_use.VoucherUse(
voucher=self,
amount=amount,
usage_type=usage_type,
justification=justification,
)
voucher_use_.save()
return voucher_use_

Copilot uses AI. Check for mistakes.
currency = self.field("currency", currency, cast=str)
unlimited = self.field("unlimited", unlimited, cast=bool)
voucher = budy.Voucher.create_value_s(key, amount, currency, unlimited)
usage_limit = object.get("usage_limit", 0)
Copy link

Copilot AI Jun 16, 2025

Choose a reason for hiding this comment

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

Consider using self.field(...) or similar validation helpers to cast and validate usage_limit, start, expiration, and meta inputs consistently, as done with the original create_value parameters.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🔭 Outside diff range comments (1)
src/budy/models/voucher.py (1)

93-141: Add missing meta field

meta is assigned in every constructor path but no appier.field exists, causing it to be stored as a volatile attribute only.

@@
     unlimited = appier.field(
         type=bool,
         initial=False,
         index=True,
         safe=True,
         observations="""Flag that indicated if the value based
         voucher should not have its used amount deducted and instead
         be considered an unlimited voucher""",
     )
+
+    meta = appier.field(
+        type=dict,
+        safe=True,
+        observations="""Arbitrary structured metadata associated with the voucher""",
+    )
🧹 Nitpick comments (4)
src/budy/models/__init__.py (1)

28-56: Missing symmetric module import for voucher_use

All other models are imported twice – once via from . import <module> (for side-effects / __all__ discovery) and again via from .<module> import <Class>.
voucher_use was only added to the second section. Add the first-stage import to keep the package initialisation pattern consistent and to ensure side-effects (signals, monkey-patches, etc.) execute.

@@
 from . import voucher
+from . import voucher_use
src/budy/models/voucher_use.py (2)

57-62: Typo in observation string

voucher,m contains a stray m.

-        observations="""Justification or reason for the usage of the voucher,m
+        observations="""Justification or reason for the usage of the voucher,

38-41: Minor: prefer literal dict over dict()

USAGE_TYPE_S = {"percentage": "percentage", "value": "value"}

Pure style; feel free to ignore if you follow a different convention.

src/budy/models/voucher.py (1)

331-347: Inconsistent return behaviour flagged by pylint

use_s returns a VoucherUse instance in one branch and None in the other. Consider always returning the created (or None) object explicitly, or returning self when save_use=False to make the API intention clearer.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4cb39d9 and 2afabeb.

📒 Files selected for processing (4)
  • src/budy/controllers/api/voucher.py (3 hunks)
  • src/budy/models/__init__.py (1 hunks)
  • src/budy/models/voucher.py (6 hunks)
  • src/budy/models/voucher_use.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/budy/models/__init__.py (1)
src/budy/models/voucher_use.py (1)
  • VoucherUse (36-96)
src/budy/models/voucher.py (1)
src/budy/models/voucher_use.py (1)
  • VoucherUse (36-96)
🪛 Ruff (0.11.9)
src/budy/models/__init__.py

87-87: .voucher_use.VoucherUse imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

🪛 Pylint (3.3.7)
src/budy/models/voucher_use.py

[refactor] 38-41: Consider using '{"percentage": 'percentage', "value": 'value'}' instead of a call to 'dict'.

(R1735)

src/budy/models/voucher.py

[refactor] 41-41: Too many public methods (28/20)

(R0904)


[refactor] 208-208: Too many arguments (9/5)

(R0913)


[refactor] 208-208: Too many positional arguments (9/5)

(R0917)


[refactor] 239-239: Too many arguments (10/5)

(R0913)


[refactor] 239-239: Too many positional arguments (10/5)

(R0917)


[refactor] 278-278: Too many arguments (7/5)

(R0913)


[refactor] 278-278: Too many positional arguments (7/5)

(R0917)


[refactor] 303-303: Too many arguments (8/5)

(R0913)


[refactor] 303-303: Too many positional arguments (8/5)

(R0917)


[refactor] 331-331: Either all return statements in a function should return an expression, or none of them should.

(R1710)

🔇 Additional comments (3)
src/budy/models/__init__.py (1)

87-87: Static-analysis false positive can be ignored

VoucherUse is deliberately imported for re-export (access via budy.VoucherUse). No further action is required; suppress the Ruff F401 rule in your config if it is too noisy.

src/budy/controllers/api/voucher.py (1)

67-75: meta accepted by the API but not persisted

meta is forwarded to Voucher.create_value_s, yet Voucher has no meta field.
Either add the field to the model or drop the parameter here to avoid user confusion.

src/budy/models/voucher.py (1)

331-346: VoucherUse receives an undefined currency argument

With the added currency field in VoucherUse, this becomes valid. If you decide not to store currency, remove the argument here to avoid a runtime TypeError when strict constructors are enabled.

Comment thread src/budy/models/voucher_use.py
Comment thread src/budy/controllers/api/voucher.py Outdated
joamag added 3 commits June 17, 2025 00:04
Implemented a new test case to validate the usage of vouchers, including checks for validity, remaining amounts, and database retrieval of usage records.
@joamag joamag merged commit dbc6921 into master Jun 16, 2025
27 checks passed
@joamag joamag deleted the feat/voucher-improvements branch June 16, 2025 23:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants