diff --git a/apps/permission/services/__init__.py b/apps/permission/services/__init__.py index e69de29..06d5079 100644 --- a/apps/permission/services/__init__.py +++ b/apps/permission/services/__init__.py @@ -0,0 +1,3 @@ +from apps.permission.services.seed_default_roles import seed_default_roles + +__all__ = ["seed_default_roles"] diff --git a/apps/permission/services/seed_default_roles.py b/apps/permission/services/seed_default_roles.py new file mode 100644 index 0000000..ebf3dc4 --- /dev/null +++ b/apps/permission/services/seed_default_roles.py @@ -0,0 +1,218 @@ +import logging + +from django_tenants.utils import schema_context + +logger = logging.getLogger(__name__) + +_ROLES = [ + {"name": "置业顾问", "category": "agent"}, + {"name": "店管", "category": "store_manager"}, + {"name": "区管", "category": "custom"}, + {"name": "区总", "category": "custom"}, + {"name": "副总", "category": "custom"}, + {"name": "总经", "category": "director"}, + {"name": "其他职能", "category": "operator"}, +] + +_T = True +_F = False +_SELF = "self" +_DEPT = "dept" +_ALL = "all" +_NONE = "none" + +_MATRIX = { + "property.listing.create": [_T, _T, _T, _T, _T, _T, _F], + "property.listing.view_scope": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.listing.view_public": [_T, _T, _T, _T, _T, _T, _F], + "property.listing.view_private": [_F, _T, _T, _T, _T, _T, _F], + "property.listing.set_public": [_T, _T, _T, _T, _T, _T, _F], + "property.listing.set_private": [_T, _T, _T, _T, _T, _T, _F], + "property.listing.set_locked": [_F, _T, _T, _T, _T, _T, _F], + "property.listing.set_special": [_F, _T, _T, _T, _T, _T, _F], + "property.listing.delete": [_F, _T, _T, _T, _T, _T, _F], + "property.listing.restore": [_F, _T, _T, _T, _T, _T, _F], + "property.listing.export": [_F, _T, _T, _T, _T, _T, _F], + "property.listing.edit_description": [_T, _T, _T, _T, _T, _T, _F], + "property.listing.view_deal": [_F, _T, _T, _T, _T, _T, _F], + "property.listing.price_read": [_T, _T, _T, _T, _T, _T, _F], + "property.listing.view_history": [_T, _T, _T, _T, _T, _T, _F], + "property.listing.view_owner_others": [_T, _T, _T, _T, _T, _T, _F], + "property.listing.set_protected": [_F, _T, _T, _T, _T, _T, _F], + "property.listing.view_protected": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.listing.change_keeper": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.listing.merge_duplicate": [_F, _T, _T, _T, _T, _T, _F], + "property.listing.status_sold": [_T, _T, _T, _T, _T, _T, _F], + "property.listing.grade_set_a": [_T, _T, _T, _T, _T, _T, _F], + "property.listing.grade_set_e": [_F, _T, _T, _T, _T, _T, _F], + "property.contact.view_phone": [_T, _T, _T, _T, _T, _T, _F], + "property.contact.view_phone_limit": [20, -1, -1, -1, -1, -1, 0], + "property.contact.add_contact": [_T, _T, _T, _T, _T, _T, _F], + "property.contact.edit_core": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.contact.edit_basic": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.contact.delete_contact": [_F, _T, _T, _T, _T, _T, _F], + "property.contact.view_cert": [_T, _T, _T, _T, _T, _T, _F], + "property.contact.view_operation_log":[_F, _T, _T, _T, _T, _T, _F], + "property.address.view_detail": [_T, _T, _T, _T, _T, _T, _F], + "property.address.view_limit": [10, -1, -1, -1, -1, -1, 0], + "property.address.edit": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.key.create": [_T, _T, _T, _T, _T, _T, _F], + "property.key.edit": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.key.return": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.key.view_password": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.key.view_number": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.key.borrow": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.key.give_back": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.key.delete": [_NONE, _SELF, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.key.export": [_F, _T, _T, _T, _T, _T, _F], + "property.survey.create_photo": [_T, _T, _T, _T, _T, _T, _F], + "property.survey.download_photo": [_T, _T, _T, _T, _T, _T, _F], + "property.survey.delete_photo": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.survey.create": [_T, _T, _T, _T, _T, _T, _F], + "property.survey.view": [_T, _T, _T, _T, _T, _T, _F], + "property.survey.upload_video": [_T, _T, _T, _T, _T, _T, _F], + "property.survey.download_video": [_T, _T, _T, _T, _T, _T, _F], + "property.survey.play_video": [_T, _T, _T, _T, _T, _T, _F], + "property.mandate.create": [_T, _T, _T, _T, _T, _T, _F], + "property.mandate.renew": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.mandate.view": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.mandate.revoke": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.mandate.export": [_F, _T, _T, _T, _T, _T, _F], + "property.follow.view_scope": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.follow.hide": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.follow.view_hidden": [_NONE, _SELF, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.follow.pin": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.attachment.create": [_T, _T, _T, _T, _T, _T, _F], + "property.attachment.view": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.attachment.edit": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.attachment.download": [_T, _T, _T, _T, _T, _T, _F], + "property.attachment.delete": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "property.showing.view_scope": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.private.create": [_T, _T, _T, _T, _T, _T, _F], + "client.private.view": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.private.view_protected": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.private.edit": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.private.edit_protected": [_SELF, _SELF, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.private.set_protected": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.private.to_public": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.private.export": [_F, _T, _T, _T, _T, _T, _F], + "client.public.view": [_NONE, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.public.to_private": [_T, _T, _T, _T, _T, _T, _F], + "client.public.edit": [_T, _T, _T, _T, _T, _T, _F], + "client.public.change_status": [_F, _T, _T, _T, _T, _T, _F], + "client.deal.view": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.deal.view_public": [_NONE, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.deal.re_transaction": [_T, _T, _T, _T, _T, _T, _F], + "client.deal.export": [_F, _T, _T, _T, _T, _T, _F], + "client.contact.view_phone_private": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.contact.view_phone_protected":[_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.contact.view_phone_public": [_NONE, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.contact.view_phone_limit": [20, -1, -1, -1, -1, -1, 0], + "client.contact.edit_contact": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.contact.edit_phone": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.mgmt.delete": [_F, _T, _T, _T, _T, _T, _F], + "client.mgmt.to_deal": [_F, _T, _T, _T, _T, _T, _F], + "client.mgmt.change_staff": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.mgmt.batch_change_staff": [_NONE, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.mgmt.view_operation_log": [_F, _T, _T, _T, _T, _T, _F], + "client.mgmt.merge_private": [_T, _T, _T, _T, _T, _T, _F], + "client.showing.create": [_T, _T, _T, _T, _T, _T, _F], + "client.showing.view": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.showing.edit": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.archive.view": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "client.archive.import": [_F, _T, _T, _T, _T, _T, _F], + "client.archive.view_phone": [_F, _T, _T, _T, _T, _T, _F], + "client.archive.delete": [_F, _T, _T, _T, _T, _T, _F], + "client.archive.view_log": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "home.dashboard.view_version": [_T, _T, _T, _T, _T, _T, _T], + "home.dashboard.personal_rank": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "home.dashboard.dept_rank": [_NONE, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "home.dashboard.manage_praise": [_F, _T, _T, _T, _T, _T, _F], + "complex.view": [_T, _T, _T, _T, _T, _T, _T], + "complex.view_structure": [_T, _T, _T, _T, _T, _T, _T], + "complex.create": [_F, _T, _T, _T, _T, _T, _F], + "complex.create_unit": [_F, _T, _T, _T, _T, _T, _F], + "complex.edit": [_F, _T, _T, _T, _T, _T, _F], + "complex.edit_unit": [_F, _T, _T, _T, _T, _T, _F], + "complex.delete": [_F, _F, _T, _T, _T, _T, _F], + "complex.delete_unit": [_F, _T, _T, _T, _T, _T, _F], + "complex.delete_with_property": [_F, _F, _F, _T, _T, _T, _F], + "complex.merge": [_F, _F, _T, _T, _T, _T, _F], + "complex.move_unit": [_F, _F, _T, _T, _T, _T, _F], + "complex.lock": [_F, _T, _T, _T, _T, _T, _F], + "complex.view_deal": [_T, _T, _T, _T, _T, _T, _F], + "complex.view_deal_detail": [_F, _T, _T, _T, _T, _T, _F], + "complex.view_address_scope": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "complex.region_manage": [_F, _F, _T, _T, _T, _T, _F], + "complex.material.view_photo": [_T, _T, _T, _T, _T, _T, _T], + "complex.material.manage_photo": [_T, _T, _T, _T, _T, _T, _F], + "complex.material.delete_photo": [_F, _T, _T, _T, _T, _T, _F], + "complex.material.download_photo": [_T, _T, _T, _T, _T, _T, _T], + "complex.material.view_attachment": [_T, _T, _T, _T, _T, _T, _T], + "complex.material.manage_attachment": [_T, _T, _T, _T, _T, _T, _F], + "complex.material.download_attachment":[_T, _T, _T, _T, _T, _T, _T], + "complex.material.delete_attachment": [_F, _T, _T, _T, _T, _T, _F], + "complex.material.view_surrounding": [_T, _T, _T, _T, _T, _T, _T], + "complex.feedback.view": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "complex.feedback.handle": [_F, _T, _T, _T, _T, _T, _F], + "org.view_structure": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _SELF], + "org.view_dept": [_F, _T, _T, _T, _T, _T, _F], + "org.edit_dept": [_F, _F, _T, _T, _T, _T, _F], + "org.view_staff": [_F, _T, _T, _T, _T, _T, _F], + "org.edit_staff": [_F, _F, _T, _T, _T, _T, _F], + "org.edit_staff_detail": [_F, _T, _T, _T, _T, _T, _F], + "org.freeze_account": [_F, _F, _T, _T, _T, _T, _F], + "org.import_staff": [_F, _F, _T, _T, _T, _T, _F], + "org.export_staff": [_F, _T, _T, _T, _T, _T, _F], + "org.view_permission": [_F, _F, _F, _T, _T, _T, _F], + "org.edit_permission": [_F, _F, _F, _T, _T, _T, _F], + "org.export_permission": [_F, _F, _F, _T, _T, _T, _F], + "org.edit_position": [_F, _F, _F, _T, _T, _T, _F], + "org.edit_role": [_F, _F, _F, _T, _T, _T, _F], + "org.view_store_list": [_F, _T, _T, _T, _T, _T, _F], + "org.export_store_list": [_F, _F, _T, _T, _T, _T, _F], + "org.view_contact_book": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _SELF], + "org.transfer_business": [_NONE, _DEPT, _DEPT, _ALL, _ALL, _ALL, _NONE], + "org.resign_apply": [_SELF, _DEPT, _DEPT, _ALL, _ALL, _ALL, _SELF], + "org.invite_onboard": [_F, _T, _T, _T, _T, _T, _F], + "org.view_contact_phone_limit": [5, -1, -1, -1, -1, -1, 5], +} + + +def seed_default_roles(schema_name: str) -> None: + from django.apps import apps + + Role = apps.get_model("fonrey_permission", "Role") + RolePermission = apps.get_model("fonrey_permission", "RolePermission") + PermissionDef = apps.get_model("fonrey_permission_def", "PermissionDef") + + perm_map = {p.code: p for p in PermissionDef.objects.all()} + + roles = [] + for role_def in _ROLES: + role, _ = Role.objects.get_or_create( + name=role_def["name"], + defaults={ + "category": role_def["category"], + "is_system_builtin": True, + "is_active": True, + }, + ) + roles.append(role) + + rp_objects = [] + for code, values in _MATRIX.items(): + perm = perm_map.get(code) + if perm is None: + logger.warning("PermissionDef not found: %s", code) + continue + for role, val in zip(roles, values): + rp_objects.append( + RolePermission( + role=role, + permission_def=perm, + value={"v": val}, + ) + ) + + RolePermission.objects.bulk_create(rp_objects, ignore_conflicts=True) diff --git a/apps/permission_def/migrations/0002_seed_permission_defs.py b/apps/permission_def/migrations/0002_seed_permission_defs.py new file mode 100644 index 0000000..9e32ff8 --- /dev/null +++ b/apps/permission_def/migrations/0002_seed_permission_defs.py @@ -0,0 +1,2358 @@ +from django.db import migrations + + +PERMISSION_DEFS = [ + { + "code": "property.listing.create", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "新增房源", + "description": "是否可新增房源", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "property.listing.view_scope", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "维护房源查看范围", + "description": "按维护人范围查看房源列表:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "property.listing.view_public", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "公盘查看", + "description": "是否可查看公盘房源", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "property.listing.view_private", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "私盘查看", + "description": "是否可查看私盘房源", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "property.listing.set_public", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "将房源改为公盘", + "description": "是否可将房源属性改为公盘", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 5, + }, + { + "code": "property.listing.set_private", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "将房源改为私盘", + "description": "是否可将房源属性改为私盘", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 6, + }, + { + "code": "property.listing.set_locked", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "将房源改为封盘", + "description": "是否可将房源属性改为封盘", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 7, + }, + { + "code": "property.listing.set_special", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "将房源改为特盘", + "description": "是否可将房源属性改为特盘", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 8, + }, + { + "code": "property.listing.delete", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "删除房源", + "description": "是否可删除房源", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 9, + }, + { + "code": "property.listing.restore", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "恢复已删除房源", + "description": "是否可恢复已删除的房源", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 10, + }, + { + "code": "property.listing.export", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "房源列表数据导出", + "description": "是否可将房源列表数据导出", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 11, + }, + { + "code": "property.listing.edit_description", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "修改房屋介绍信息", + "description": "是否可修改营销标题、核心卖点、户型介绍等介绍信息", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 12, + }, + { + "code": "property.listing.view_deal", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "成交房源列表及价格信息", + "description": "是否可查看成交房源列表及价格历史", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 13, + }, + { + "code": "property.listing.price_read", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "价格解读", + "description": "是否可查看房源详情页的价格解读", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 14, + }, + { + "code": "property.listing.view_history", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "查看房源挂牌历史", + "description": "是否可查看房源挂牌历史记录", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 15, + }, + { + "code": "property.listing.view_owner_others", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "查看同业主其他房源", + "description": "是否可在房源详情页查看同业主的其他房源", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 16, + }, + { + "code": "property.listing.set_protected", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "修改房源保护设置", + "description": "是否可修改房源的保护期/保护房设置", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 17, + }, + { + "code": "property.listing.view_protected", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "查看保护期内房源", + "description": "是否可查看保护期内(我租/我售/已售/已租)房源", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 18, + }, + { + "code": "property.listing.change_keeper", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "修改相关方范围", + "description": "可修改哪个范围内房源的相关方:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 19, + }, + { + "code": "property.listing.merge_duplicate", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "重复房源合并", + "description": "是否可合并重复房源", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 20, + }, + { + "code": "property.listing.status_sold", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "修改为我售/我租状态", + "description": "是否可修改房源为我售/我租状态", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 21, + }, + { + "code": "property.listing.grade_set_a", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "将房源等级设为A", + "description": "是否可将挂牌中房源等级设为A(急迫)", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 22, + }, + { + "code": "property.listing.grade_set_e", + "module": "property", + "sub_module": "listing", + "group_name": "房源基础", + "name": "将房源等级设为E", + "description": "是否可将房源等级设为E(暂不关注)", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 23, + }, + { + "code": "property.contact.view_phone", + "module": "property", + "sub_module": "contact", + "group_name": "业主/联系人与号码", + "name": "查看业主/联系人号码", + "description": "是否可查看房源业主/联系人真实号码", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "property.contact.view_phone_limit", + "module": "property", + "sub_module": "contact", + "group_name": "业主/联系人与号码", + "name": "每日查看号码次数上限", + "description": "每天可查看房源真实号码次数,0=不允许,-1=不限制", + "value_type": "integer", + "scope_choices": [], + "integer_min": -1, + "integer_max": None, + "default_value": {"v": 0}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "property.contact.add_contact", + "module": "property", + "sub_module": "contact", + "group_name": "业主/联系人与号码", + "name": "新增业主/联系人", + "description": "是否可新增业主/联系人", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "property.contact.edit_core", + "module": "property", + "sub_module": "contact", + "group_name": "业主/联系人与号码", + "name": "修改业主核心信息", + "description": "可修改哪个范围的业主核心信息(电话/微信):无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "property.contact.edit_basic", + "module": "property", + "sub_module": "contact", + "group_name": "业主/联系人与号码", + "name": "修改业主非核心信息", + "description": "可修改哪个范围的业主基本信息(姓名/备注):无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 5, + }, + { + "code": "property.contact.delete_contact", + "module": "property", + "sub_module": "contact", + "group_name": "业主/联系人与号码", + "name": "删除业主/联系人", + "description": "是否可删除业主/联系人", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 6, + }, + { + "code": "property.contact.view_cert", + "module": "property", + "sub_module": "contact", + "group_name": "业主/联系人与号码", + "name": "查看产证信息", + "description": "是否可查看房源详情页产证信息", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 7, + }, + { + "code": "property.contact.view_operation_log", + "module": "property", + "sub_module": "contact", + "group_name": "业主/联系人与号码", + "name": "查看业主联系人操作日志", + "description": "是否可查看业主/联系人的新增、修改、删除等记录", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 8, + }, + { + "code": "property.address.view_detail", + "module": "property", + "sub_module": "address", + "group_name": "房源地址", + "name": "查看楼栋/单元/楼层/房号", + "description": "是否可查看房源真实地址详情", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "property.address.view_limit", + "module": "property", + "sub_module": "address", + "group_name": "房源地址", + "name": "每日查看地址次数上限", + "description": "每天可查看房源真实地址总次数,0=不允许,-1=不限制", + "value_type": "integer", + "scope_choices": [], + "integer_min": -1, + "integer_max": None, + "default_value": {"v": 0}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "property.address.edit", + "module": "property", + "sub_module": "address", + "group_name": "房源地址", + "name": "修改楼栋/单元/楼层/房号", + "description": "是否可修改房源地址信息", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "property.key.create", + "module": "property", + "sub_module": "key", + "group_name": "房源钥匙", + "name": "新增钥匙", + "description": "是否可新增钥匙", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "property.key.edit", + "module": "property", + "sub_module": "key", + "group_name": "房源钥匙", + "name": "修改钥匙", + "description": "按钥匙方范围可修改钥匙:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "property.key.return", + "module": "property", + "sub_module": "key", + "group_name": "房源钥匙", + "name": "退还钥匙", + "description": "按钥匙方范围控制是否可退还钥匙:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "property.key.view_password", + "module": "property", + "sub_module": "key", + "group_name": "房源钥匙", + "name": "查看钥匙密码", + "description": "按钥匙方范围控制是否可查看密码:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "property.key.view_number", + "module": "property", + "sub_module": "key", + "group_name": "房源钥匙", + "name": "查看钥匙编号", + "description": "按钥匙方范围控制是否可查看钥匙编号:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 5, + }, + { + "code": "property.key.borrow", + "module": "property", + "sub_module": "key", + "group_name": "房源钥匙", + "name": "钥匙借出", + "description": "按钥匙保管部门范围借出钥匙:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 6, + }, + { + "code": "property.key.give_back", + "module": "property", + "sub_module": "key", + "group_name": "房源钥匙", + "name": "钥匙归还", + "description": "按钥匙保管部门范围归还钥匙:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 7, + }, + { + "code": "property.key.delete", + "module": "property", + "sub_module": "key", + "group_name": "房源钥匙", + "name": "删除钥匙", + "description": "按钥匙方范围控制是否可删除钥匙:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 8, + }, + { + "code": "property.key.export", + "module": "property", + "sub_module": "key", + "group_name": "房源钥匙", + "name": "钥匙列表数据导出", + "description": "是否可导出钥匙数据", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 9, + }, + { + "code": "property.survey.create_photo", + "module": "property", + "sub_module": "survey", + "group_name": "房源实勘", + "name": "新增实勘图片", + "description": "是否可新增实勘图片", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "property.survey.download_photo", + "module": "property", + "sub_module": "survey", + "group_name": "房源实勘", + "name": "下载图片", + "description": "是否可下载实勘图片", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "property.survey.delete_photo", + "module": "property", + "sub_module": "survey", + "group_name": "房源实勘", + "name": "删除图片", + "description": "按图片上传人范围删除:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "property.survey.create", + "module": "property", + "sub_module": "survey", + "group_name": "房源实勘", + "name": "新增实勘", + "description": "是否可新增实勘记录", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "property.survey.view", + "module": "property", + "sub_module": "survey", + "group_name": "房源实勘", + "name": "查看实勘", + "description": "是否可查看实勘记录", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 5, + }, + { + "code": "property.survey.upload_video", + "module": "property", + "sub_module": "survey", + "group_name": "房源实勘", + "name": "上传视频", + "description": "是否可上传房源视频", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 6, + }, + { + "code": "property.survey.download_video", + "module": "property", + "sub_module": "survey", + "group_name": "房源实勘", + "name": "下载视频", + "description": "是否可下载房源视频", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 7, + }, + { + "code": "property.survey.play_video", + "module": "property", + "sub_module": "survey", + "group_name": "房源实勘", + "name": "播放视频", + "description": "是否可播放房源视频", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 8, + }, + { + "code": "property.mandate.create", + "module": "property", + "sub_module": "mandate", + "group_name": "房源委托", + "name": "新增委托", + "description": "是否可新增房源委托", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "property.mandate.renew", + "module": "property", + "sub_module": "mandate", + "group_name": "房源委托", + "name": "续签/违约委托", + "description": "按委托方范围可续签或违约委托:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "property.mandate.view", + "module": "property", + "sub_module": "mandate", + "group_name": "房源委托", + "name": "委托列表查看", + "description": "按委托方范围查看委托列表:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "property.mandate.revoke", + "module": "property", + "sub_module": "mandate", + "group_name": "房源委托", + "name": "委托作废", + "description": "按委托方范围控制是否可作废委托:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "property.mandate.export", + "module": "property", + "sub_module": "mandate", + "group_name": "房源委托", + "name": "委托列表数据导出", + "description": "是否可导出委托列表数据", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 5, + }, + { + "code": "property.follow.view_scope", + "module": "property", + "sub_module": "follow", + "group_name": "房源跟进", + "name": "查看房源跟进范围", + "description": "控制房源详情页的跟进查看范围:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "property.follow.hide", + "module": "property", + "sub_module": "follow", + "group_name": "房源跟进", + "name": "隐藏/开放跟进", + "description": "按跟进人范围隐藏/开放跟进:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "property.follow.view_hidden", + "module": "property", + "sub_module": "follow", + "group_name": "房源跟进", + "name": "查看隐藏跟进", + "description": "按跟进人范围查看被隐藏的跟进:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "property.follow.pin", + "module": "property", + "sub_module": "follow", + "group_name": "房源跟进", + "name": "置顶/取消置顶跟进", + "description": "按跟进人范围置顶或取消置顶跟进:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "property.attachment.create", + "module": "property", + "sub_module": "attachment", + "group_name": "房源附件", + "name": "新增附件", + "description": "是否可新增房源附件", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "property.attachment.view", + "module": "property", + "sub_module": "attachment", + "group_name": "房源附件", + "name": "查看附件", + "description": "按附件上传人范围查看:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "property.attachment.edit", + "module": "property", + "sub_module": "attachment", + "group_name": "房源附件", + "name": "修改附件", + "description": "按附件上传人范围修改:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "property.attachment.download", + "module": "property", + "sub_module": "attachment", + "group_name": "房源附件", + "name": "下载附件", + "description": "是否可下载房源附件", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "property.attachment.delete", + "module": "property", + "sub_module": "attachment", + "group_name": "房源附件", + "name": "删除附件", + "description": "按附件上传人范围删除:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 5, + }, + { + "code": "property.showing.view_scope", + "module": "property", + "sub_module": "showing", + "group_name": "房源带看", + "name": "查看房源带看数据", + "description": "按数据权限范围查看房源带看记录:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "client.private.create", + "module": "client", + "sub_module": "private", + "group_name": "私客", + "name": "新增私客", + "description": "是否可新增私客", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "client.private.view", + "module": "client", + "sub_module": "private", + "group_name": "私客", + "name": "查看私客(非保护客)", + "description": "按归属人范围查看非保护私客:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "client.private.view_protected", + "module": "client", + "sub_module": "private", + "group_name": "私客", + "name": "查看私客(保护客)", + "description": "按归属人范围查看保护私客:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "client.private.edit", + "module": "client", + "sub_module": "private", + "group_name": "私客", + "name": "编辑私客(非保护客)", + "description": "按归属人范围编辑非保护私客:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "client.private.edit_protected", + "module": "client", + "sub_module": "private", + "group_name": "私客", + "name": "编辑私客(保护客)", + "description": "按归属人范围编辑保护私客:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 5, + }, + { + "code": "client.private.set_protected", + "module": "client", + "sub_module": "private", + "group_name": "私客", + "name": "设置/取消保护客", + "description": "设置/取消哪个范围的保护客:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 6, + }, + { + "code": "client.private.to_public", + "module": "client", + "sub_module": "private", + "group_name": "私客", + "name": "私客转公客", + "description": "按归属人范围将私客转为公客:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 7, + }, + { + "code": "client.private.export", + "module": "client", + "sub_module": "private", + "group_name": "私客", + "name": "私客列表导出", + "description": "是否支持导出私客列表", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 8, + }, + { + "code": "client.public.view", + "module": "client", + "sub_module": "public", + "group_name": "公客", + "name": "公客查看范围", + "description": "控制公客查看范围:无/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "client.public.to_private", + "module": "client", + "sub_module": "public", + "group_name": "公客", + "name": "公客转私客", + "description": "是否可将可见范围内的公客转为私客", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "client.public.edit", + "module": "client", + "sub_module": "public", + "group_name": "公客", + "name": "编辑公客", + "description": "是否可编辑公客信息", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "client.public.change_status", + "module": "client", + "sub_module": "public", + "group_name": "公客", + "name": "改公客状态", + "description": "是否可修改公客状态", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "client.deal.view", + "module": "client", + "sub_module": "deal", + "group_name": "成交客", + "name": "查看成交客(私客类型)", + "description": "按归属人范围查看归属人为个人的成交客:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "client.deal.view_public", + "module": "client", + "sub_module": "deal", + "group_name": "成交客", + "name": "查看成交客(公客类型)", + "description": "按归属人范围查看归属人为共享账号的成交客:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "client.deal.re_transaction", + "module": "client", + "sub_module": "deal", + "group_name": "成交客", + "name": "成交客再次租/购", + "description": "是否可对可见范围内成交客操作再次租/购", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "client.deal.export", + "module": "client", + "sub_module": "deal", + "group_name": "成交客", + "name": "导出成交客列表", + "description": "是否可导出成交客列表", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "client.contact.view_phone_private", + "module": "client", + "sub_module": "contact", + "group_name": "联系人号码", + "name": "查看私客/成交客号码", + "description": "控制查看非保护私客及成交客的号码范围:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "client.contact.view_phone_protected", + "module": "client", + "sub_module": "contact", + "group_name": "联系人号码", + "name": "查看保护客号码", + "description": "控制查看保护私客的号码范围:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "client.contact.view_phone_public", + "module": "client", + "sub_module": "contact", + "group_name": "联系人号码", + "name": "查看公客号码", + "description": "控制查看公客号码范围:无/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "client.contact.view_phone_limit", + "module": "client", + "sub_module": "contact", + "group_name": "联系人号码", + "name": "每日查看联系人号码次数上限", + "description": "每天可查看客源联系人真实号码次数,0=不允许,-1=不限制", + "value_type": "integer", + "scope_choices": [], + "integer_min": -1, + "integer_max": None, + "default_value": {"v": 0}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "client.contact.edit_contact", + "module": "client", + "sub_module": "contact", + "group_name": "联系人号码", + "name": "编辑私客/成交客联系人", + "description": "控制编辑非保护私客及成交客联系人信息范围:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 5, + }, + { + "code": "client.contact.edit_phone", + "module": "client", + "sub_module": "contact", + "group_name": "联系人号码", + "name": "编辑私客/成交客联系人号码", + "description": "控制编辑非保护私客及成交客联系人号码范围:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 6, + }, + { + "code": "client.mgmt.delete", + "module": "client", + "sub_module": "mgmt", + "group_name": "客源管理", + "name": "删除客源", + "description": "是否可删除客源及查看已删除客源", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "client.mgmt.to_deal", + "module": "client", + "sub_module": "mgmt", + "group_name": "客源管理", + "name": "手动客源转为成交客", + "description": "是否可手动将客源标记为成交客", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "client.mgmt.change_staff", + "module": "client", + "sub_module": "mgmt", + "group_name": "客源管理", + "name": "单个客源修改相关员工", + "description": "可修改哪个范围内客源的相关方:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "client.mgmt.batch_change_staff", + "module": "client", + "sub_module": "mgmt", + "group_name": "客源管理", + "name": "批量客源修改相关员工", + "description": "批量修改哪个范围内客源的相关方:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "client.mgmt.view_operation_log", + "module": "client", + "sub_module": "mgmt", + "group_name": "客源管理", + "name": "查看客户/联系人操作日志", + "description": "是否可查看客户详情页手机号修改/删除、客户合并等记录", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 5, + }, + { + "code": "client.mgmt.merge_private", + "module": "client", + "sub_module": "mgmt", + "group_name": "客源管理", + "name": "允许合并自己的私客", + "description": "是否可合并归属人为本人的私客", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 6, + }, + { + "code": "client.showing.create", + "module": "client", + "sub_module": "showing", + "group_name": "带看/预约", + "name": "带看/预约新增", + "description": "是否可新增带看/预约记录", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "client.showing.view", + "module": "client", + "sub_module": "showing", + "group_name": "带看/预约", + "name": "私客/成交客详情页带看单查看", + "description": "按带看人范围查看私客/成交客的带看单:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "client.showing.edit", + "module": "client", + "sub_module": "showing", + "group_name": "带看/预约", + "name": "带看/预约编辑、作废", + "description": "按带看人范围编辑或作废带看:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "client.archive.view", + "module": "client", + "sub_module": "archive", + "group_name": "资料客", + "name": "查看资料客", + "description": "按归属人范围查看资料客:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "client.archive.import", + "module": "client", + "sub_module": "archive", + "group_name": "资料客", + "name": "导入资料客", + "description": "是否可导入资料客", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "client.archive.view_phone", + "module": "client", + "sub_module": "archive", + "group_name": "资料客", + "name": "查看资料客号码", + "description": "是否可查看资料客号码", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "client.archive.delete", + "module": "client", + "sub_module": "archive", + "group_name": "资料客", + "name": "删除资料客", + "description": "是否可删除资料客", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "client.archive.view_log", + "module": "client", + "sub_module": "archive", + "group_name": "资料客", + "name": "查看资料客操作日志", + "description": "查看哪个范围员工的资料客操作日志:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 5, + }, + { + "code": "home.dashboard.view_version", + "module": "home", + "sub_module": "dashboard", + "group_name": "首页看板", + "name": "查看首页版本", + "description": "控制员工可查看的首页数据版本(置业顾问/店管/区管等)", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "home.dashboard.personal_rank", + "module": "home", + "sub_module": "dashboard", + "group_name": "首页看板", + "name": "个人排行榜权限", + "description": "控制个人排行榜可见数据范围:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "home.dashboard.dept_rank", + "module": "home", + "sub_module": "dashboard", + "group_name": "首页看板", + "name": "部门排行榜权限", + "description": "控制部门排行榜可见数据范围:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "home.dashboard.manage_praise", + "module": "home", + "sub_module": "dashboard", + "group_name": "首页看板", + "name": "管理点赞信息和屏蔽点赞", + "description": "是否可删除首页点赞墙内容和禁止员工发布", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "complex.view", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "楼盘管理查看", + "description": "是否显示楼盘管理模块", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "complex.view_structure", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "楼盘结构查看", + "description": "是否可查看楼栋-单元-房号层级结构", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "complex.create", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "新增楼盘", + "description": "是否可新增或批量新增楼盘", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "complex.create_unit", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "新增楼栋/单元/房号", + "description": "是否可新增楼栋、单元、房号数据", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "complex.edit", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "编辑楼盘", + "description": "是否可编辑楼盘信息", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 5, + }, + { + "code": "complex.edit_unit", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "编辑楼栋/单元/房号", + "description": "是否可编辑楼栋、单元、房号信息", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 6, + }, + { + "code": "complex.delete", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "删除楼盘", + "description": "是否可删除楼盘", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 7, + }, + { + "code": "complex.delete_unit", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "删除楼栋/单元/房号", + "description": "是否可删除楼栋、单元、房号", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 8, + }, + { + "code": "complex.delete_with_property", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "删除楼盘数据(含房源)", + "description": "是否可无视房源直接删除楼盘及以下所有数据", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 9, + }, + { + "code": "complex.merge", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "合并楼盘", + "description": "是否可合并不同层级楼盘数据", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 10, + }, + { + "code": "complex.move_unit", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "移动楼栋/单元/房号数据", + "description": "是否可将楼栋单元数据移动至其他楼盘", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 11, + }, + { + "code": "complex.lock", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "锁定/解锁楼盘", + "description": "是否可操作锁定或解锁楼盘", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 12, + }, + { + "code": "complex.view_deal", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "楼盘挂牌成交数据", + "description": "是否显示楼盘挂牌及成交数据", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 13, + }, + { + "code": "complex.view_deal_detail", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "司内成交明细及套数", + "description": "是否显示公司成交房源明细信息及套数", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 14, + }, + { + "code": "complex.view_address_scope", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "楼街房源地址数据查看范围", + "description": "控制查看部门内其他员工楼街房源地址数据:本人/本部/全部", + "value_type": "scope", + "scope_choices": ["self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 15, + }, + { + "code": "complex.region_manage", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘管理", + "name": "区域管理", + "description": "是否可对区域商圈进行新增、合并、关联操作", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 16, + }, + { + "code": "complex.material.view_photo", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘资料", + "name": "楼盘照片", + "description": "是否显示楼盘照片列表", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "complex.material.manage_photo", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘资料", + "name": "管理照片", + "description": "是否可上传照片、设为封面", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "complex.material.delete_photo", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘资料", + "name": "删除照片", + "description": "是否可删除楼盘照片", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "complex.material.download_photo", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘资料", + "name": "下载照片", + "description": "是否可下载楼盘照片", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "complex.material.view_attachment", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘资料", + "name": "楼盘附件", + "description": "是否显示楼盘附件模块", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 5, + }, + { + "code": "complex.material.manage_attachment", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘资料", + "name": "管理附件", + "description": "是否可上传楼盘附件", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 6, + }, + { + "code": "complex.material.download_attachment", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘资料", + "name": "下载附件", + "description": "是否可下载楼盘附件", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 7, + }, + { + "code": "complex.material.delete_attachment", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘资料", + "name": "删除附件", + "description": "是否可删除楼盘附件", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 8, + }, + { + "code": "complex.material.view_surrounding", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘资料", + "name": "周边配套", + "description": "是否显示周边配套模块", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 9, + }, + { + "code": "complex.feedback.view", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘反馈", + "name": "楼盘反馈列表", + "description": "可查看小区反馈列表的数据范围:本人/本部/全部", + "value_type": "scope", + "scope_choices": ["self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "complex.feedback.handle", + "module": "property", + "sub_module": "complex", + "group_name": "楼盘反馈", + "name": "楼盘反馈处理", + "description": "是否可处理或不予处理楼盘反馈", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "org.view_structure", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "组织结构查看", + "description": "控制组织结构页面的部门/员工查看范围:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 1, + }, + { + "code": "org.view_dept", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "部门查看", + "description": "是否可查看部门信息", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 2, + }, + { + "code": "org.edit_dept", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "部门维护", + "description": "是否可对部门进行编辑操作", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 3, + }, + { + "code": "org.view_staff", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "员工查看", + "description": "是否可查看员工详情", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 4, + }, + { + "code": "org.edit_staff", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "员工维护", + "description": "是否可进行员工异动、批量设置员工上级等操作", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 5, + }, + { + "code": "org.edit_staff_detail", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "员工详情编辑", + "description": "是否可编辑员工信息、新增奖惩记录、编辑账号信息", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 6, + }, + { + "code": "org.freeze_account", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "员工账号冻结/解冻", + "description": "是否可冻结/解冻员工账号", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 7, + }, + { + "code": "org.import_staff", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "批量导入员工", + "description": "是否可批量导入员工", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 8, + }, + { + "code": "org.export_staff", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "导出员工", + "description": "是否可导出员工数据", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 9, + }, + { + "code": "org.view_permission", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "员工权限查看", + "description": "是否可查看员工权限配置", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 10, + }, + { + "code": "org.edit_permission", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "员工权限设置", + "description": "是否可编辑员工权限", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 11, + }, + { + "code": "org.export_permission", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "权限管理页面导出", + "description": "是否可在权限管理页面导出员工角色及管理范围数据", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 12, + }, + { + "code": "org.edit_position", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "职务维护", + "description": "是否可新增/编辑/删除/合并员工职务", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 13, + }, + { + "code": "org.edit_role", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "角色维护", + "description": "是否可展示角色管理页面并进行角色编辑", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 14, + }, + { + "code": "org.view_store_list", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "门店列表查看", + "description": "是否可查看门店列表", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 15, + }, + { + "code": "org.export_store_list", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "门店列表导出", + "description": "是否可导出门店列表", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 16, + }, + { + "code": "org.view_contact_book", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "员工通讯录查看", + "description": "控制查看员工通讯录的范围:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 17, + }, + { + "code": "org.transfer_business", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "转移业务归属", + "description": "控制转出/转入人的可选范围:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "none"}, + "max_allowed_categories": [], + "sort_order": 18, + }, + { + "code": "org.resign_apply", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "离职申请范围", + "description": "控制员工离职申请范围:无/本人/本部/全部", + "value_type": "scope", + "scope_choices": ["none", "self", "dept", "all"], + "integer_min": None, + "integer_max": None, + "default_value": {"v": "self"}, + "max_allowed_categories": [], + "sort_order": 19, + }, + { + "code": "org.invite_onboard", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "入职邀请", + "description": "是否可生成入职邀请链接/二维码", + "value_type": "boolean", + "scope_choices": [], + "integer_min": None, + "integer_max": None, + "default_value": {"v": False}, + "max_allowed_categories": [], + "sort_order": 20, + }, + { + "code": "org.view_contact_phone_limit", + "module": "hr", + "sub_module": "org", + "group_name": "组织管理", + "name": "每日查看通讯录电话次数上限", + "description": "每天可查看员工通讯录电话次数,0=不允许,-1=不限制", + "value_type": "integer", + "scope_choices": [], + "integer_min": -1, + "integer_max": None, + "default_value": {"v": 0}, + "max_allowed_categories": [], + "sort_order": 21, + }, +] + + +def forwards(apps, schema_editor): + PermissionDef = apps.get_model("fonrey_permission_def", "PermissionDef") + objs = [ + PermissionDef( + code=d["code"], + module=d["module"], + sub_module=d["sub_module"], + group_name=d["group_name"], + name=d["name"], + description=d["description"], + value_type=d["value_type"], + scope_choices=d["scope_choices"], + integer_min=d["integer_min"], + integer_max=d["integer_max"], + default_value=d["default_value"], + max_allowed_categories=d["max_allowed_categories"], + sort_order=d["sort_order"], + is_active=True, + is_deprecated=False, + is_system=True, + version=1, + ) + for d in PERMISSION_DEFS + ] + PermissionDef.objects.bulk_create(objs, ignore_conflicts=False) + + +def backwards(apps, schema_editor): + PermissionDef = apps.get_model("fonrey_permission_def", "PermissionDef") + codes = [d["code"] for d in PERMISSION_DEFS] + PermissionDef.objects.filter(code__in=codes).delete() + + +class Migration(migrations.Migration): + dependencies = [ + ("fonrey_permission_def", "0001_initial"), + ] + + operations = [ + migrations.RunPython(forwards, backwards), + ] diff --git a/apps/setting/services/__init__.py b/apps/setting/services/__init__.py index e69de29..1f1fa4f 100644 --- a/apps/setting/services/__init__.py +++ b/apps/setting/services/__init__.py @@ -0,0 +1,3 @@ +from apps.setting.services.seed_default_lookups import seed_default_lookups + +__all__ = ["seed_default_lookups"] diff --git a/apps/setting/services/seed_default_lookups.py b/apps/setting/services/seed_default_lookups.py new file mode 100644 index 0000000..8ff4260 --- /dev/null +++ b/apps/setting/services/seed_default_lookups.py @@ -0,0 +1,113 @@ +import logging + +logger = logging.getLogger(__name__) + +_GROUPS = [ + {"module": "client", "key": "source", "label_zh": "客源来源", "description": "客源从何处获取,用于来源渠道分析", "sort_order": 1}, + {"module": "client", "key": "follow_purpose", "label_zh": "跟进目的", "description": "客源跟进时选择的目的分类", "sort_order": 2}, + {"module": "property", "key": "source", "label_zh": "房源来源", "description": "房源从何处获取", "sort_order": 3}, +] + +_ITEMS = { + ("client", "source"): [ + {"value": "store_reception", "label_zh": "门店接待", "sort_order": 1}, + {"value": "old_client_referral", "label_zh": "老客户转介绍", "sort_order": 2}, + {"value": "stationed_dispatch", "label_zh": "驻守派单", "sort_order": 3}, + {"value": "walk_in", "label_zh": "上门", "sort_order": 4}, + {"value": "online_58", "label_zh": "网络-58同城", "sort_order": 5}, + {"value": "online_anjuke", "label_zh": "网络-安居客", "sort_order": 6}, + {"value": "wechat", "label_zh": "微信", "sort_order": 7}, + {"value": "friend_referral", "label_zh": "朋友介绍", "sort_order": 8}, + ], + ("client", "follow_purpose"): [ + {"value": "callback", "label_zh": "回拨", "sort_order": 1}, + {"value": "push_property", "label_zh": "推房", "sort_order": 2}, + {"value": "showing", "label_zh": "带看", "sort_order": 3}, + {"value": "maintain", "label_zh": "维护", "sort_order": 4}, + {"value": "other", "label_zh": "其他", "sort_order": 5}, + ], + ("property", "source"): [ + {"value": "proactive_development", "label_zh": "主动开发", "sort_order": 1}, + {"value": "owner_walk_in", "label_zh": "业主上门", "sort_order": 2}, + {"value": "old_client_referral", "label_zh": "老客户转介绍", "sort_order": 3}, + {"value": "online_inquiry", "label_zh": "网络来电", "sort_order": 4}, + ], +} + +_TENANT_SETTINGS = [ + {"category": "client", "key": "duplicate_check_scope", "value": {"v": "self"}, "value_type": "enum"}, +] + +_FIELD_RULES = [ + {"module": "property", "entity_type": "residential", "trade_status": "sale", "field_key": "orientation", "requirement": "optional"}, + {"module": "property", "entity_type": "residential", "trade_status": "sale", "field_key": "decoration", "requirement": "optional"}, + {"module": "property", "entity_type": "residential", "trade_status": "sale", "field_key": "floor", "requirement": "optional"}, + {"module": "property", "entity_type": "residential", "trade_status": "sale", "field_key": "building_area", "requirement": "required"}, + {"module": "property", "entity_type": "residential", "trade_status": "sale", "field_key": "inner_area", "requirement": "optional"}, + {"module": "property", "entity_type": "residential", "trade_status": "sale", "field_key": "room_layout", "requirement": "required"}, + {"module": "property", "entity_type": "residential", "trade_status": "rent", "field_key": "decoration", "requirement": "optional"}, + {"module": "property", "entity_type": "residential", "trade_status": "rent", "field_key": "floor", "requirement": "optional"}, + {"module": "property", "entity_type": "residential", "trade_status": "rent", "field_key": "building_area", "requirement": "required"}, + {"module": "property", "entity_type": "residential", "trade_status": "rent", "field_key": "room_layout", "requirement": "required"}, +] + + +def seed_default_lookups(schema_name: str) -> None: + from django.apps import apps + + LookupGroup = apps.get_model("fonrey_setting", "LookupGroup") + LookupItem = apps.get_model("fonrey_setting", "LookupItem") + TenantSetting = apps.get_model("fonrey_setting", "TenantSetting") + FieldRequirementRule = apps.get_model("fonrey_setting", "FieldRequirementRule") + + group_map = {} + for gd in _GROUPS: + group, _ = LookupGroup.objects.get_or_create( + module=gd["module"], + key=gd["key"], + defaults={ + "label_zh": gd["label_zh"], + "description": gd["description"], + "sort_order": gd["sort_order"], + }, + ) + group_map[(gd["module"], gd["key"])] = group + + item_objects = [] + for (module, key), items in _ITEMS.items(): + group = group_map[(module, key)] + for item in items: + item_objects.append( + LookupItem( + group=group, + value=item["value"], + label_zh=item["label_zh"], + is_system=True, + is_active=True, + sort_order=item["sort_order"], + ) + ) + LookupItem.objects.bulk_create(item_objects, ignore_conflicts=True) + + ts_objects = [ + TenantSetting( + category=ts["category"], + key=ts["key"], + value=ts["value"], + value_type=ts["value_type"], + ) + for ts in _TENANT_SETTINGS + ] + TenantSetting.objects.bulk_create(ts_objects, ignore_conflicts=True) + + rule_objects = [ + FieldRequirementRule( + module=r["module"], + entity_type=r["entity_type"], + trade_status=r["trade_status"], + field_key=r["field_key"], + requirement=r["requirement"], + ) + for r in _FIELD_RULES + ] + FieldRequirementRule.objects.bulk_create(rule_objects, ignore_conflicts=True) diff --git a/apps/tenant/apps.py b/apps/tenant/apps.py index 94e22b2..11fc974 100644 --- a/apps/tenant/apps.py +++ b/apps/tenant/apps.py @@ -5,3 +5,8 @@ class TenantConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" name = "apps.tenant" label = "tenant" + + def ready(self): + from apps.tenant import signals # noqa: F401 + + signals._register() diff --git a/apps/tenant/signals.py b/apps/tenant/signals.py new file mode 100644 index 0000000..4f5d9b9 --- /dev/null +++ b/apps/tenant/signals.py @@ -0,0 +1,36 @@ +import logging + +from django.db.models.signals import post_save +from django.dispatch import receiver + +logger = logging.getLogger(__name__) + + +def _get_tenant_model(): + from django.apps import apps + return apps.get_model("tenant", "Tenant") + + +def _register(): + Tenant = _get_tenant_model() + + @receiver(post_save, sender=Tenant) + def on_tenant_created(sender, instance, created, **kwargs): + if not created: + return + if instance.schema_name == "public": + return + + from django_tenants.utils import schema_context + + from apps.permission.services import seed_default_roles + from apps.setting.services import seed_default_lookups + + try: + with schema_context(instance.schema_name): + seed_default_roles(instance.schema_name) + seed_default_lookups(instance.schema_name) + except Exception: + logger.exception( + "Failed to seed defaults for tenant %s", instance.schema_name + )