-
Notifications
You must be signed in to change notification settings - Fork 12
feat: teams v1 #5
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
Changes from all commits
d8b5c74
bf2ac51
383524f
0a180a5
f4fe1e8
6d02cc3
7198d5a
7a6a337
0f5c26a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import frappe | ||
|
|
||
| from forms_pro.utils.teams import GetTeamFormsResponseSchema | ||
| from forms_pro.utils.teams import get_team_forms as get_team_forms_utils | ||
|
|
||
|
|
||
| @frappe.whitelist() | ||
| def get_team_forms(team_id: str) -> list[GetTeamFormsResponseSchema]: | ||
| """ | ||
| Get the list of forms for the current team | ||
|
|
||
| Args: | ||
| team_id: ID of the team | ||
|
|
||
| Returns: | ||
| list[GetTeamFormsResponseSchema] - List of forms for the team | ||
| """ | ||
| forms = get_team_forms_utils(team_id=team_id) | ||
| return forms | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| import frappe | ||
| from frappe.core.doctype.has_role.has_role import HasRole | ||
| from pydantic import BaseModel, Field, field_validator | ||
|
|
||
| from forms_pro.utils.teams import get_user_teams as get_user_teams_utils | ||
|
|
||
|
|
||
| class GetUserTeamsResponseSchema(BaseModel): | ||
| name: str = Field(description="ID of the team") | ||
| team_name: str = Field(description="The name of the team") | ||
| is_current: bool = Field(description="Whether this is the current team") | ||
|
|
||
|
|
||
| class GetUserResponseSchema(BaseModel): | ||
| email: str | ||
| first_name: str | ||
| last_name: str | None = None | ||
| full_name: str | ||
| username: str | ||
| desk_theme: str | ||
| roles: list[str] | ||
| has_desk_access: bool | ||
|
|
||
| @field_validator("roles", mode="before") | ||
| @classmethod | ||
| def extract_roles(cls, v: list[HasRole]) -> list[str]: | ||
| if not v: | ||
| return [] | ||
|
|
||
| return [role.role for role in v] | ||
|
|
||
|
|
||
| @frappe.whitelist() | ||
| def get_user() -> GetUserResponseSchema: | ||
| """ | ||
| Get Current User Data | ||
| """ | ||
|
|
||
| user_id = frappe.session.user | ||
| user_doc = frappe.get_doc("User", user_id) | ||
| data = user_doc.as_dict() | ||
| data["roles"] = user_doc.get("roles") | ||
| data["has_desk_access"] = user_doc.has_desk_access() | ||
|
|
||
| return GetUserResponseSchema.model_validate(data).model_dump() | ||
|
harshtandiya marked this conversation as resolved.
|
||
|
|
||
|
|
||
| @frappe.whitelist() | ||
| def get_user_teams() -> list[GetUserTeamsResponseSchema]: | ||
| """ | ||
| Get the list of teams for the current user | ||
| """ | ||
|
|
||
| user = frappe.session.user | ||
|
|
||
| if user == "Guest": | ||
| return [] | ||
|
|
||
| teams = get_user_teams_utils(user) | ||
|
|
||
| return [GetUserTeamsResponseSchema.model_validate(team).model_dump() for team in teams] | ||
|
harshtandiya marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,6 +4,8 @@ | |||||||||||||||
| import frappe | ||||||||||||||||
| from frappe.tests import IntegrationTestCase | ||||||||||||||||
|
|
||||||||||||||||
| from forms_pro.utils.teams import get_user_teams | ||||||||||||||||
|
|
||||||||||||||||
| # On IntegrationTestCase, the doctype test records and all | ||||||||||||||||
| # link-field test record dependencies are recursively loaded | ||||||||||||||||
| # Use these module variables to add/remove to/from that list | ||||||||||||||||
|
|
@@ -18,9 +20,18 @@ def setUp(self): | |||||||||||||||
| self.test_doctype_name = "Test Form DocType" | ||||||||||||||||
| self.create_test_doctype() | ||||||||||||||||
|
|
||||||||||||||||
| self.test_user = "test_forms_pro_user@example.com" | ||||||||||||||||
| self.test_team = get_user_teams(self.test_user)[0]["name"] | ||||||||||||||||
|
|
||||||||||||||||
|
Comment on lines
+23
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find . -name "install.py" -o -name "*fixture*" -o -name "*setup*" | head -20Repository: BuildWithHussain/forms_pro Length of output: 113 🏁 Script executed: rg -n "test_forms_pro_user@example.com" -A 5 -B 5Repository: BuildWithHussain/forms_pro Length of output: 2308 🏁 Script executed: rg -n "def get_user_teams" -A 15Repository: BuildWithHussain/forms_pro Length of output: 1637 🏁 Script executed: rg -n "def setUp|def setUpClass" -B 2 -A 10 forms_pro/forms_pro/doctype/form/test_form.pyRepository: BuildWithHussain/forms_pro Length of output: 564 🏁 Script executed: cat -n forms_pro/forms_pro/doctype/form/test_form.py | head -40Repository: BuildWithHussain/forms_pro Length of output: 1679 🏁 Script executed: cat -n forms_pro/install.pyRepository: BuildWithHussain/forms_pro Length of output: 1019 🏁 Script executed: rg -n "FP Team" -B 3 -A 10 forms_pro/install.pyRepository: BuildWithHussain/forms_pro Length of output: 52 🏁 Script executed: cat -n forms_pro/utils/test_form_generator.py | head -30Repository: BuildWithHussain/forms_pro Length of output: 1331 🏁 Script executed: rg -n "FP Team" forms_pro/ -A 5 | head -50Repository: BuildWithHussain/forms_pro Length of output: 3097 🏁 Script executed: ls -la forms_pro/fixtures/Repository: BuildWithHussain/forms_pro Length of output: 239 🏁 Script executed: cat forms_pro/fixtures/*.json 2>/dev/null | head -100Repository: BuildWithHussain/forms_pro Length of output: 352 🏁 Script executed: cat -n forms_pro/overrides/roles.pyRepository: BuildWithHussain/forms_pro Length of output: 1820 🏁 Script executed: rg -n "def.*after_insert|def.*on_update" forms_pro/overrides/roles.py -B 2 -A 15Repository: BuildWithHussain/forms_pro Length of output: 52 Guard against IndexError when retrieving test team. The test user is created with the "Forms Pro User" role during test setup, which should automatically create a default team through the Suggested fix: self.test_user = "test_forms_pro_user@example.com"
-self.test_team = get_user_teams(self.test_user)[0]["name"]
+user_teams = get_user_teams(self.test_user)
+self.assertGreater(len(user_teams), 0, f"User {self.test_user} has no teams")
+self.test_team = user_teams[0]["name"]📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||
| # Create a test Form | ||||||||||||||||
| self.test_form = frappe.get_doc( | ||||||||||||||||
| {"doctype": "Form", "title": "Test Form", "linked_doctype": self.test_doctype_name, "fields": []} | ||||||||||||||||
| { | ||||||||||||||||
| "doctype": "Form", | ||||||||||||||||
| "title": "Test Form", | ||||||||||||||||
| "linked_doctype": self.test_doctype_name, | ||||||||||||||||
| "fields": [], | ||||||||||||||||
| "linked_team_id": self.test_team, | ||||||||||||||||
| } | ||||||||||||||||
| ) | ||||||||||||||||
| self.test_form.insert() | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| import frappe | ||
| from frappe.core.doctype.user.user import User | ||
|
|
||
| from forms_pro.roles import FORMS_PRO_ROLE | ||
|
|
||
|
|
||
| def before_tests(): | ||
| give_admin_forms_pro_role() | ||
| create_test_user() | ||
|
|
||
|
|
||
| def give_admin_forms_pro_role(): | ||
| admin = frappe.get_doc("User", "Administrator") | ||
| admin.append("roles", {"role": FORMS_PRO_ROLE}) | ||
| admin.save() | ||
|
Comment on lines
+12
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check for existing role before appending. Line 14 appends the Forms Pro role without checking if it already exists. If 🔎 Recommended fix to prevent duplicate roles def give_admin_forms_pro_role():
admin = frappe.get_doc("User", "Administrator")
- admin.append("roles", {"role": FORMS_PRO_ROLE})
+ if not any(r.role == FORMS_PRO_ROLE for r in admin.roles):
+ admin.append("roles", {"role": FORMS_PRO_ROLE})
admin.save()🤖 Prompt for AI Agents |
||
|
|
||
|
|
||
| def create_test_user(): | ||
| test_user = "test_forms_pro_user@example.com" | ||
|
|
||
| if frappe.db.exists("User", test_user): | ||
| return | ||
|
|
||
| user: User = frappe.new_doc("User") | ||
| user.email = test_user | ||
| user.first_name = "Test" | ||
| user.last_name = "Forms Pro User" | ||
| user.insert(ignore_permissions=True) | ||
| user.append("roles", {"role": FORMS_PRO_ROLE}) | ||
| user.save(ignore_permissions=True) | ||
|
Comment on lines
+18
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check for existing role before appending. Line 29 appends the Forms Pro role without checking if it already exists. While this is less critical than in 🔎 Recommended fix to prevent duplicate roles user: User = frappe.new_doc("User")
user.email = test_user
user.first_name = "Test"
user.last_name = "Forms Pro User"
user.insert(ignore_permissions=True)
- user.append("roles", {"role": FORMS_PRO_ROLE})
+ if not any(r.role == FORMS_PRO_ROLE for r in user.roles):
+ user.append("roles", {"role": FORMS_PRO_ROLE})
user.save(ignore_permissions=True)🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,12 +4,12 @@ | |
|
|
||
|
|
||
| @frappe.whitelist() | ||
| def create_form_with_doctype(doctype: str): | ||
| def create_form_with_doctype(team_id: str, doctype: str): | ||
| roles = frappe.get_roles(frappe.session.user) | ||
| if FORMS_PRO_ROLE not in roles: | ||
| frappe.throw("You are not authorized to create a form") | ||
|
harshtandiya marked this conversation as resolved.
|
||
|
|
||
| form_generator = FormGenerator(linked_doctype=doctype) | ||
| form_generator = FormGenerator(team_id=team_id, linked_doctype=doctype) | ||
| form_generator.generate() | ||
|
|
||
| return { | ||
|
|
@@ -19,12 +19,12 @@ def create_form_with_doctype(doctype: str): | |
|
|
||
|
|
||
| @frappe.whitelist() | ||
| def create_form(): | ||
| def create_form(team_id: str): | ||
| roles = frappe.get_roles(frappe.session.user) | ||
| if FORMS_PRO_ROLE not in roles: | ||
| frappe.throw("You are not authorized to create a form") | ||
|
|
||
| form_generator = FormGenerator() | ||
| form_generator = FormGenerator(team_id=team_id) | ||
| form_generator.generate() | ||
|
|
||
| return { | ||
|
|
@@ -34,8 +34,13 @@ def create_form(): | |
|
|
||
|
|
||
| class FormGenerator: | ||
| def __init__(self, linked_doctype: str | None = None) -> None: | ||
| def __init__( | ||
| self, | ||
| team_id: str, | ||
| linked_doctype: str | None = None, | ||
| ) -> None: | ||
| self.doctype = None | ||
| self.team_id = team_id | ||
|
Comment on lines
+37
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing validation for The Consider adding validation: 🔎 Suggested fix def __init__(
self,
team_id: str,
linked_doctype: str | None = None,
) -> None:
+ if not team_id:
+ frappe.throw("Team ID is required to create a form")
self.doctype = None
self.team_id = team_id🤖 Prompt for AI Agents |
||
| if linked_doctype: | ||
| self.doctype = frappe.get_doc("DocType", linked_doctype) | ||
|
|
||
|
|
@@ -80,6 +85,7 @@ def _initialize_form_document(self) -> None: | |
| form_document = frappe.new_doc("Form") | ||
| form_document.linked_doctype = self.doctype.name | ||
| form_document.title = "Untitled Form" | ||
| form_document.linked_team_id = self.team_id | ||
| form_document.insert(ignore_permissions=True) | ||
| self.form_document = form_document | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.