Skip to content

Conversation

@harshtandiya
Copy link
Collaborator

@harshtandiya harshtandiya commented Dec 24, 2025

  • Created a different module for Form Pro User Doctype called User Forms
  • Share the DocType and the Form to the user creating it
  • Tests added

Summary by CodeRabbit

  • New Features

    • Optional linking for generated forms
    • Generated forms and their schemas now create shared access entries
  • Improvements

    • Improved error handling and logging during form creation
    • Cache cleared during generation to ensure fresh state
  • Tests

    • New tests verifying creation of share entries; updated expectations for module grouping
  • Chores

    • Forms reorganized under "User Forms"
    • CI updated to Python 3.12

✏️ Tip: You can customize this high-level summary in your review settings.

…agement

- Added error handling in create_form to log and throw exceptions.
- Updated DocType module name to "User Forms".
- Implemented permissions management for DocType and Form documents using DocShare.
- Added tests to verify DocShare creation with correct permissions for both DocType and Form.
@coderabbitai
Copy link

coderabbitai bot commented Dec 24, 2025

Warning

Rate limit exceeded

@harshtandiya has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minutes and 36 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 3433fb5 and 91b062e.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml
📝 Walkthrough

Walkthrough

Module list now includes "User Forms". FormGenerator gained an optional linked_doctype parameter, added permission checks, error handling and cache clearing, and creates DocShares for both the generated DocType and Form; generated DocType module changed from "Forms Pro" to "User Forms". Tests updated accordingly.

Changes

Cohort / File(s) Summary
Module Configuration
forms_pro/modules.txt
Appended User Forms as a module entry (original Forms Pro line retained).
Form Generator Core Logic
forms_pro/utils/form_generator.py
Constructor signature extended with optional linked_doctype; permission checks raise translated errors; generation wrapped in try/except with logging; calls frappe.clear_cache(); _initialize_doctype now uses module "User Forms", sets multiple doctype flags to 0, adds a permissions table and a Section Break field, inserts with ignore_permissions=True, and calls add_docshare for the DocType; _initialize_form_document sets document_type="System" and also calls add_docshare for the Form.
Tests
forms_pro/utils/test_form_generator.py
Updated expectations from Forms ProUser Forms; added tests asserting DocShare entries are created for the generated DocType and the Form with read/write/share enabled and submit disabled.
CI Configuration
.github/workflows/ci.yml
Updated Python setup version from 3.10 to 3.12; CI env var value normalized to a string.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant FormGenerator
    participant FrappeCache as "Frappe Cache"
    participant DocTypeService as "DocType"
    participant DocShareService as "DocShare"
    participant FormDoc as "Form Document"

    Client->>FormGenerator: generate(team_id, linked_doctype?)
    FormGenerator->>FrappeCache: clear_cache()
    FormGenerator->>DocTypeService: _generate_doctype_name()
    FormGenerator->>DocTypeService: _initialize_doctype(..., module="User Forms")
    Note right of DocTypeService: flags set to 0\npermissions added\nsection break field
    DocTypeService->>DocTypeService: insert(ignore_permissions=true)
    FormGenerator->>DocShareService: add_docshare(doctype, user, ignore_share_permission=True)
    FormGenerator->>FormDoc: _initialize_form_document(document_type="System")
    FormDoc->>FormDoc: insert(...)
    FormGenerator->>DocShareService: add_docshare(form, user, ignore_share_permission=True)
    FormGenerator-->>Client: return created form
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped and stitched a new form bright,
"User Forms" now blooms in the night,
Shares snugly wrapped with access clear,
Cache swept clean so changes appear,
A rabbit's cheer — permissions right!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.55% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title is vague and generic, using the non-descriptive term 'better' without conveying meaningful information about the actual changes (new module, DocShare implementation, tests). Use a more descriptive title that reflects the main changes, such as 'feat: separate User Forms module and add DocShare permissions' or 'refactor: add form sharing and separate User Forms module'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
forms_pro/utils/form_generator.py (1)

159-159: Inconsistent module filter in DocType name generation.

The _generate_doctype_name method counts existing DocTypes from the "Forms Pro" module, but new DocTypes are created with module "User Forms" (Line 65). This inconsistency could lead to name collisions or incorrect serial numbers.

Consider updating the filter to count DocTypes from "User Forms" module instead:

🔎 Proposed fix
-        count = frappe.db.count("DocType", filters={"module": "Forms Pro", "name": ["like", "formspro_%"]})
+        count = frappe.db.count("DocType", filters={"module": "User Forms", "name": ["like", "formspro_%"]})

Alternatively, if you want to maintain continuity with existing DocTypes, count from both modules:

count = frappe.db.count("DocType", filters={"module": ["in", ["Forms Pro", "User Forms"]], "name": ["like", "formspro_%"]})
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8f5269b and 81c605e.

📒 Files selected for processing (4)
  • forms_pro/modules.txt
  • forms_pro/user_forms/__init__.py
  • forms_pro/utils/form_generator.py
  • forms_pro/utils/test_form_generator.py
🧰 Additional context used
🧬 Code graph analysis (1)
forms_pro/utils/test_form_generator.py (1)
forms_pro/utils/form_generator.py (2)
  • FormGenerator (43-170)
  • generate (54-57)
🪛 Ruff (0.14.10)
forms_pro/utils/form_generator.py

32-32: Do not catch blind exception: Exception

(BLE001)

🔇 Additional comments (8)
forms_pro/modules.txt (1)

1-2: LGTM!

The addition of the "User Forms" module entry is clean and aligns with the module name used in the DocType initialization.

forms_pro/utils/test_form_generator.py (2)

77-77: LGTM!

The module assertion updates correctly reflect the module name change from "Forms Pro" to "User Forms" in the implementation.

Also applies to: 136-136


161-213: Excellent test coverage for DocShare functionality!

The new tests thoroughly verify that DocShare entries are created with correct permissions for both the DocType and Form documents. The tests appropriately set user context and validate all expected permission flags.

forms_pro/utils/form_generator.py (5)

44-48: LGTM!

The addition of type hints improves code clarity and makes the API more explicit.


57-57: LGTM!

Adding cache clearing ensures that newly created DocTypes and Forms are immediately visible throughout the system.


65-96: Good DocType initialization with explicit configuration.

The changes improve the DocType initialization by:

  • Explicitly setting all relevant flags to 0 for clarity
  • Adding a permissions entry for System Manager
  • Including a Section Break field
  • Updating the module name to "User Forms"

100-110: LGTM!

The DocShare implementation correctly grants the creating user read, write, and share permissions on the DocType, while appropriately excluding submit permissions. The use of ignore_share_permission flag is necessary for creation.


137-137: LGTM!

The Form initialization correctly sets document_type to "System" and implements DocShare with appropriate permissions matching the DocType pattern.

Also applies to: 140-150

Comment on lines 29 to 36
try:
form_generator = FormGenerator(team_id=team_id)
form_generator.generate()
except Exception as e:
frappe.log_error(f"Error creating form: {e}")
frappe.throw(f"Error creating form: {e}")
print(frappe.get_traceback())

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix error handling issues.

The error handling has several issues:

  1. Catching bare Exception is too broad and can mask unexpected errors. Consider catching specific exceptions.
  2. Line 35 is unreachable because frappe.throw() on Line 34 raises an exception.
  3. The error is both logged and thrown, which may result in duplicate error reporting.
🔎 Proposed fix
-    try:
-        form_generator = FormGenerator(team_id=team_id)
-        form_generator.generate()
-    except Exception as e:
-        frappe.log_error(f"Error creating form: {e}")
-        frappe.throw(f"Error creating form: {e}")
-        print(frappe.get_traceback())
+    form_generator = FormGenerator(team_id=team_id)
+    form_generator.generate()

If error handling is required for specific exceptions, catch those explicitly and remove the unreachable print statement.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff (0.14.10)

32-32: Do not catch blind exception: Exception

(BLE001)

🤖 Prompt for AI Agents
In forms_pro/utils/form_generator.py around lines 29 to 36, replace the current
broad try/except that catches Exception, logs, calls frappe.throw (making the
following print unreachable) and prints the traceback; instead catch only the
specific exceptions you expect from FormGenerator (e.g., ValueError, KeyError or
a custom FormGenerationError), call frappe.log_error with the full traceback and
context when one of those specific exceptions occurs, then re-raise the original
exception (using plain raise) so the framework handles it — do not call
frappe.throw and remove the unreachable print(frappe.get_traceback()) to avoid
duplicate reporting.

Copy link

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
forms_pro/utils/form_generator.py (1)

148-164: Fix module filter mismatch in DocType counting.

The _generate_doctype_name method counts DocTypes from the "Forms Pro" module (Line 154), but _initialize_doctype creates DocTypes in the "User Forms" module (Line 78). This mismatch means:

  1. The counter will never include newly created DocTypes
  2. Multiple DocTypes may receive the same sequence number
  3. This could lead to naming collisions
🔎 Proposed fix
     def _generate_doctype_name(self) -> str:
         """
         Generate a unique DocType name with format: formspro_XXXXXX_YYYYYY
         where XXXXXX is a random 6-character string and YYYYYY is a serialized number
         """
-        # Count existing formspro_* DocTypes from Forms Pro module
-        count = frappe.db.count("DocType", filters={"module": "Forms Pro", "name": ["like", "formspro_%"]})
+        # Count existing formspro_* DocTypes from User Forms module
+        count = frappe.db.count("DocType", filters={"module": "User Forms", "name": ["like", "formspro_%"]})
 
         # Next number is count + 1
         next_number = count + 1

Alternatively, if you want to count both old and new modules during migration:

-        # Count existing formspro_* DocTypes from Forms Pro module
-        count = frappe.db.count("DocType", filters={"module": "Forms Pro", "name": ["like", "formspro_%"]})
+        # Count existing formspro_* DocTypes from both Forms Pro and User Forms modules
+        count = frappe.db.count("DocType", filters={"name": ["like", "formspro_%"]})
🧹 Nitpick comments (1)
forms_pro/utils/form_generator.py (1)

70-70: Consider targeted cache clearing for better performance.

frappe.clear_cache() clears all caches globally, which can be expensive in production. Since you're only creating a DocType and Form, consider clearing specific caches instead.

🔎 Alternative approach
-        frappe.clear_cache()
+        frappe.clear_cache(doctype="DocType")
+        frappe.clear_cache(doctype="Form")

Or use frappe.cache().delete_value() for even more targeted clearing if you know the specific cache keys.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 81c605e and 4c088a6.

📒 Files selected for processing (1)
  • forms_pro/utils/form_generator.py
🧰 Additional context used
🪛 Ruff (0.14.10)
forms_pro/utils/form_generator.py

20-20: Do not catch blind exception: Exception

(BLE001)


44-44: Do not catch blind exception: Exception

(BLE001)

🔇 Additional comments (7)
forms_pro/utils/form_generator.py (7)

2-3: LGTM!

The new imports support translation and DocShare functionality introduced in this PR.


78-88: LGTM!

Module renamed to "User Forms" per PR objectives, and flags are explicitly initialized to ensure predictable defaults.


108-109: LGTM!

Adding a placeholder Section Break field ensures the DocType has at least one field, which is a valid approach for template DocTypes.


135-145: Verify DocShare is created for the correct user.

Same as the DocType sharing: confirm that add_docshare shares the Form with the user who created it by default.


17-24: Catch specific exceptions instead of bare Exception.

Catching bare Exception is too broad and can mask unexpected errors like KeyboardInterrupt, SystemExit, or programming bugs. Review the FormGenerator.generate() method to determine what exceptions it can actually raise, then catch only those specific exception types rather than the catch-all Exception.


90-106: Clarify the dual-access permission model.

The code grants "System Manager" role-based permissions while also using DocShare to provide the creating user direct access. Verify this design is intentional: users without "System Manager" role should still have full access through DocShare, but role-based access controls may be confusing or unnecessary in this context.


41-48: Catch specific exceptions instead of bare Exception.

Same issue as in create_form_with_doctype: catching bare Exception is too broad and can mask unexpected errors. Adjust the caught exception types based on what FormGenerator and generate() can raise.

Comment on lines +113 to +123
add_docshare(
"DocType",
placeholder_doctype.name,
read=1,
write=1,
share=1,
submit=0,
flags={
"ignore_share_permission": True,
},
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Search for add_docshare definition in the codebase
rg "def add_docshare" -B 2 -A 10

Repository: BuildWithHussain/forms_pro

Length of output: 196


🏁 Script executed:

# Also search for imports of add_docshare to understand where it comes from
rg "add_docshare" --type py -B 2 -A 2 | head -50

Repository: BuildWithHussain/forms_pro

Length of output: 196


🏁 Script executed:

# Check the specific file to see the import statement
cat -n forms_pro/utils/form_generator.py | head -30

Repository: BuildWithHussain/forms_pro

Length of output: 196


🌐 Web query:

Frappe add_docshare function parameters default user

💡 Result:

The add_docshare function signature in Frappe is commonly called as:

add_docshare(doctype, name, user=None, everyone=None, read=0, write=0, submit=0, share=0).

  • user defaults to None (pass a user email/ID to share with a specific user). [1][2]

Sources:

  1. Frappe forum example showing usage with user and write flag. [1]
  2. Frappe repository share.py (function definition / implementation). [2]

🌐 Web query:

frappe.share.add_docshare documentation user parameter

💡 Result:

The user parameter is the user identifier (the User.name / email string) to share the document with — e.g. frappe.session.user or each user from a User Group (pass a string like "user@example.com"). Examples and usage in the Frappe forum show calls such as add_docshare(doctype, name, user=frappe.session.user, ...) and looping over User Group members passing user.user. [1][2]

Sources:

  • Frappe forum example using add_docshare with user parameter. [1]
  • Frappe forum custom-script example calling frappe.share.call with user: frappe.session.user. [2]

Add user=frappe.session.user to the add_docshare call.

The add_docshare function defaults the user parameter to None, not the current user. To share the DocType with the user who created it, explicitly pass user=frappe.session.user to the function call at line 114.

🤖 Prompt for AI Agents
In forms_pro/utils/form_generator.py around lines 113 to 123, the add_docshare
call is not passing the creating user so the share will not be tied to the
session user; update the add_docshare invocation to include
user=frappe.session.user (i.e., add the user keyword argument to the existing
parameter list) so the DocType is shared with the current session user; ensure
frappe.session is referenced where this function runs.

Copy link

@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: 1

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4c088a6 and 3433fb5.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml
🔇 Additional comments (1)
.github/workflows/ci.yml (1)

99-99: Verify the CI environment variable type change.

The CI variable was changed from a boolean (Yes) to a string ("Yes"). While this likely won't cause issues, please confirm that frappe-bench handles both formats correctly, as this change wasn't mentioned in the PR description.

uses: actions/setup-python@v4
with:
python-version: '3.10'
python-version: "3.12"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

frappe-bench Python 3.12 compatibility support

💡 Result:

Short answer

  • Frappe/bench itself can work with Python 3.12 in recent releases, but official stable documentation and supported-stack recommendations still list Python 3.10+ as the baseline for production. Use Python 3.10 (or 3.11 where explicitly documented) for the most reliable results unless you are using a develop/bleeding-edge branch that explicitly adds 3.12 support. [1][2][3][4]

Details (concise)

  • Official install docs (current stable lines) list Python 3.10+ as the required Python version. This is the safe production target. [1]
  • bench releases have added the ability to create venvs with a chosen Python interpreter; that allows using Python 3.12 if your bench release and the Frappe branch support it. Check your bench version and release notes. [3]
  • Frappe/ERPNext app compatibility varies by major version. Community/issue threads show Python 3.12 support being added/worked on in the develop branches (and some users report running ERPNext on 3.12), but several stable app versions (e.g., v14/v15 historically) required 3.10 minimum and needed explicit fixes for 3.12. Verify the specific Frappe/ERPNext branch you plan to run. [2][4]

Recommendation

  • For production: use the Python version listed in the official docs for the Frappe/ERPNext release you plan to run (usually 3.10; confirm per-release). [1]
  • If you want to test Python 3.12: use a non-production environment, upgrade bench to the latest release, use the develop/branch that lists py3.12 support, run tests/migrations, and watch for package issues (RestrictedPython, other deps). [3][4]

If you tell me which Frappe/ERPNext version and your OS (Ubuntu release), I’ll check the exact branch docs and confirm whether that version has explicit Python 3.12 support and any required workarounds.

Sources

  • Frappe install docs (system requirements). [1]
  • Frappe/ERPNext forum discussions re: Python 3.12 compatibility. [2][4]
  • frappe/bench release notes (venv/python handling). [3]

Verify Python 3.12 compatibility with your Frappe/ERPNext version.

Python 3.12 is not officially stable in most frappe-bench releases; official documentation recommends Python 3.10+. While recent bench releases and develop branches may support 3.12, confirm that your specific Frappe/ERPNext version explicitly supports Python 3.12 and has no known compatibility issues before merging this change.

🤖 Prompt for AI Agents
.github/workflows/ci.yml around line 49: the workflow sets python-version to
"3.12" but many Frappe/ERPNext releases officially support up to Python 3.10;
verify your exact Frappe/ERPNext and bench versions explicitly support 3.12
before merging. Either change the workflow to a known-supported version (e.g.,
3.10), or convert the job to a matrix that runs 3.10 (required) and 3.12
(optional) so CI validates compatibility; update the PR with links to the tested
Frappe/ERPNext/bench commit ranges and add a short note in the workflow header
describing why 3.12 is included (or remove it if unsupported).

@harshtandiya harshtandiya merged commit cb147c4 into develop Dec 24, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants