before change Ticket Desc to TextArea

This commit is contained in:
mohammad javad fesahat committed 2024-07-25 09:06:30 +03:30
1 parent f7dbd02a6c
commit ef18434b86
55 files changed
+1026 -59

No files matched your search

+2
View File
@@ -7,6 +7,8 @@ __pycache__/
# C extensions # C extensions
*.so *.so
*.xlsx
# Distribution / packaging # Distribution / packaging
.Python .Python
build/ build/
+10
View File
@@ -0,0 +1,10 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# GitHub Copilot persisted chat sessions
/copilot/chatSessions
Generated
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="accountSettings">
<option name="activeProfile" value="profile:default" />
<option name="activeRegion" value="us-east-1" />
<option name="recentlyUsedProfiles">
<list>
<option value="profile:default" />
</list>
</option>
<option name="recentlyUsedRegions">
<list>
<option value="us-east-1" />
</list>
</option>
</component>
<component name="connectionManager">
<option name="activeConnectionId" value="sso;us-east-1;https://view.awsapps.com/start" />
</component>
</project>
+5 -2
View File
@@ -13,8 +13,11 @@
</facet> </facet>
</component> </component>
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" /> <content url="file://$MODULE_DIR$">
<orderEntry type="inheritedJdk" /> <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.10" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
<component name="PyDocumentationSettings"> <component name="PyDocumentationSettings">
+4 -1
View File
@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="crmApiEnv" project-jdk-type="Python SDK" /> <component name="Black">
<option name="sdkName" value="Python 3.12 (venv)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" project-jdk-type="Python SDK" />
</project> </project>
+174 -14
View File
@@ -1,16 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="87c5db51-3e89-4a98-9bbb-121c9c52ab3c" name="Changes" comment=""> <list default="true" id="87c5db51-3e89-4a98-9bbb-121c9c52ab3c" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/.idea/.gitignore" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/aws.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/crmApi.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/crmApi.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/cuser/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/cuser/models.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/customer/selectors.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/customer/selectors.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/jwt_auth/services.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/jwt_auth/services.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/lead/selectors.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/lead/selectors.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/lead/views.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/lead/views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/shop/admin.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/admin.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/shop/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/models.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/apps/shop/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/models.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/shop/selectors/cart.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/selectors/cart.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/shop/selectors/order.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/selectors/order.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/apps/shop/selectors/order.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/selectors/order.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/shop/selectors/product.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/selectors/product.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/shop/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/urls.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/apps/shop/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/urls.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/shop/views/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/views/__init__.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/apps/shop/views/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/views/__init__.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/shop/views/excel_import.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/views/excel_import.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/shop/views/order.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/views/order.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/apps/shop/views/order.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/views/order.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/shop/views/product.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/views/product.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/apps/shop/views/product.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/views/product.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/apps/shop/views/product_category.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/shop/views/product_category.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/apps/workspace/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/apps/workspace/models.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/config/asgi.py" beforeDir="false" afterPath="$PROJECT_DIR$/config/asgi.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/config/settings/base.py" beforeDir="false" afterPath="$PROJECT_DIR$/config/settings/base.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/config/settings/production.py" beforeDir="false" afterPath="$PROJECT_DIR$/config/settings/production.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/config/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/config/urls.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/config/wsgi.py" beforeDir="false" afterPath="$PROJECT_DIR$/config/wsgi.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/requirements/base.txt" beforeDir="false" afterPath="$PROJECT_DIR$/requirements/base.txt" afterDir="false" /> <change beforePath="$PROJECT_DIR$/requirements/base.txt" beforeDir="false" afterPath="$PROJECT_DIR$/requirements/base.txt" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
@@ -34,23 +54,35 @@
<component name="MarkdownSettingsMigration"> <component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" /> <option name="stateVersion" value="1" />
</component> </component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 3
}</component>
<component name="ProjectId" id="2SvKNIPBcTXVjDKPSdS8NHW9I0w" /> <component name="ProjectId" id="2SvKNIPBcTXVjDKPSdS8NHW9I0w" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" /> <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState"> <component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" /> <option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" /> <option name="showLibraryContents" value="true" />
</component> </component>
<component name="PropertiesComponent">{ <component name="PropertiesComponent"><![CDATA[{
&quot;keyToString&quot;: { "keyToString": {
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;, "Django Server.crmApi.executor": "Run",
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;, "RunOnceActivity.OpenDjangoStructureViewOnStart": "true",
&quot;WebServerToolWindowFactoryState&quot;: &quot;false&quot;, "RunOnceActivity.OpenProjectViewOnStart": "true",
&quot;last_opened_file_path&quot;: &quot;E:/Projects/crmProject/Project/api-Project/crmApi&quot;, "RunOnceActivity.ShowReadmeOnStart": "true",
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;, "SHARE_PROJECT_CONFIGURATION_FILES": "true",
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;, "WebServerToolWindowFactoryState": "false",
&quot;settings.editor.selected.configurable&quot;: &quot;com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable&quot; "git-widget-placeholder": "main",
"ignore.virus.scanning.warn.message": "true",
"last_opened_file_path": "C:/Users/mjavad/Projects/crmProject/Project/api-Project/crmApi",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "http.proxy",
"vue.rearranger.settings.migration": "true"
} }
}</component> }]]></component>
<component name="RecentsManager"> <component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS"> <key name="MoveFile.RECENT_KEYS">
<recent name="E:\Projects\crmProject\Project\api-Project\crmApi\utils" /> <recent name="E:\Projects\crmProject\Project\api-Project\crmApi\utils" />
@@ -60,13 +92,14 @@
<component name="RunManager"> <component name="RunManager">
<configuration name="crmApi" type="Python.DjangoServer" factoryName="Django server"> <configuration name="crmApi" type="Python.DjangoServer" factoryName="Django server">
<module name="crmApi" /> <module name="crmApi" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" /> <option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" /> <option name="PARENT_ENVS" value="true" />
<envs> <envs>
<env name="PYTHONUNBUFFERED" value="1" /> <env name="PYTHONUNBUFFERED" value="1" />
</envs> </envs>
<option name="SDK_HOME" value="" /> <option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" /> <option name="WORKING_DIRECTORY" value="C:\Users\mjavad\Projects\crmProject\Project\api-Project\crmApi" />
<option name="IS_MODULE_SDK" value="true" /> <option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" /> <option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" /> <option name="ADD_SOURCE_ROOTS" value="true" />
@@ -82,6 +115,14 @@
<method v="2" /> <method v="2" />
</configuration> </configuration>
</component> </component>
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="bundled-js-predefined-1d06a55b98c1-74d2a5396914-JavaScript-PY-241.14494.241" />
<option value="bundled-python-sdk-0509580d9d50-28c9f5db9ffe-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-241.14494.241" />
</set>
</attachedChunks>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" /> <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager"> <component name="TaskManager">
<task active="true" id="Default" summary="Default task"> <task active="true" id="Default" summary="Default task">
@@ -100,7 +141,38 @@
<workItem from="1702900258020" duration="63755000" /> <workItem from="1702900258020" duration="63755000" />
<workItem from="1704088148329" duration="105568000" /> <workItem from="1704088148329" duration="105568000" />
<workItem from="1704951046597" duration="135372000" /> <workItem from="1704951046597" duration="135372000" />
<workItem from="1706950546279" duration="9716000" /> <workItem from="1706950546279" duration="21524000" />
<workItem from="1707974605580" duration="43207000" />
<workItem from="1710141658112" duration="240000" />
<workItem from="1710142130443" duration="1078000" />
<workItem from="1710150399673" duration="961000" />
<workItem from="1710419485683" duration="68525000" />
<workItem from="1710488609275" duration="177000" />
<workItem from="1710488798818" duration="2376000" />
<workItem from="1710491283739" duration="274000" />
<workItem from="1710491571470" duration="2407000" />
<workItem from="1710859420770" duration="5021000" />
<workItem from="1711518197148" duration="371000" />
<workItem from="1711518633367" duration="2351000" />
<workItem from="1711525074800" duration="90000" />
<workItem from="1711525175741" duration="553000" />
<workItem from="1711525746440" duration="138000" />
<workItem from="1711525904502" duration="187000" />
<workItem from="1711526396806" duration="5937000" />
<workItem from="1711602888442" duration="717000" />
<workItem from="1711606336704" duration="5357000" />
<workItem from="1711869672173" duration="628000" />
<workItem from="1711878111438" duration="700000" />
<workItem from="1711880635851" duration="981000" />
<workItem from="1712055178474" duration="84000" />
<workItem from="1713166182071" duration="22113000" />
<workItem from="1714581267648" duration="6000" />
<workItem from="1714884894390" duration="1477000" />
<workItem from="1715065792878" duration="1238000" />
<workItem from="1715426896536" duration="10640000" />
<workItem from="1719038043515" duration="2436000" />
<workItem from="1720441183640" duration="1046000" />
<workItem from="1720442591368" duration="302000" />
</task> </task>
<servers /> <servers />
</component> </component>
@@ -118,4 +190,92 @@
</map> </map>
</option> </option>
</component> </component>
<component name="XDebuggerManager">
<breakpoint-manager>
<breakpoints>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/shop/views/excel_import.py</url>
<line>16</line>
<option name="timeStamp" value="2" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/shop/views/excel_import.py</url>
<line>19</line>
<option name="timeStamp" value="3" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/shop/views/excel_import.py</url>
<line>21</line>
<option name="timeStamp" value="4" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/shop/views/excel_import.py</url>
<line>23</line>
<option name="timeStamp" value="5" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/shop/views/excel_import.py</url>
<line>29</line>
<option name="timeStamp" value="6" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/shop/views/excel_import.py</url>
<line>30</line>
<option name="timeStamp" value="7" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/shop/views/excel_import.py</url>
<line>39</line>
<option name="timeStamp" value="8" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/jwt_auth/services.py</url>
<line>14</line>
<option name="timeStamp" value="13" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/jwt_auth/services.py</url>
<line>17</line>
<option name="timeStamp" value="14" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/jwt_auth/services.py</url>
<line>19</line>
<option name="timeStamp" value="15" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/jwt_auth/services.py</url>
<line>20</line>
<option name="timeStamp" value="16" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/jwt_auth/services.py</url>
<line>37</line>
<option name="timeStamp" value="17" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/jwt_auth/services.py</url>
<line>38</line>
<option name="timeStamp" value="18" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/jwt_auth/views.py</url>
<line>116</line>
<option name="timeStamp" value="19" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/apps/jwt_auth/views.py</url>
<line>118</line>
<option name="timeStamp" value="20" />
</line-breakpoint>
</breakpoints>
<default-breakpoints>
<breakpoint type="python-exception">
<properties notifyOnTerminate="true" exception="BaseException">
<option name="notifyOnTerminate" value="true" />
</properties>
</breakpoint>
</default-breakpoints>
</breakpoint-manager>
</component>
</project> </project>
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-04-16 06:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cuser', '0011_cuserrole_customer_panel'),
]
operations = [
migrations.AddField(
model_name='cuserrole',
name='is_admin',
field=models.BooleanField(blank=True, default=None, null=True),
),
]
+1
View File
@@ -26,6 +26,7 @@ class CuserRole(BaseModel):
mobile = models.PositiveBigIntegerField(null=False, blank=False) mobile = models.PositiveBigIntegerField(null=False, blank=False)
mobile_verify = models.BooleanField(default=False) mobile_verify = models.BooleanField(default=False)
customer_panel = models.BooleanField(default=None, blank=True, null=True) customer_panel = models.BooleanField(default=None, blank=True, null=True)
is_admin = models.BooleanField(default=None, blank=True, null=True)
sys_ws = models.ForeignKey(WorkspaceModel, on_delete=models.CASCADE, null=True, blank=True, default=None) sys_ws = models.ForeignKey(WorkspaceModel, on_delete=models.CASCADE, null=True, blank=True, default=None)
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
-1
View File
@@ -101,7 +101,6 @@ def customer_form_item(request):
'shahr': shahr, 'shahr': shahr,
'responsible_groups': responsible_groups 'responsible_groups': responsible_groups
} }
return data return data
@@ -0,0 +1,19 @@
# Generated by Django 4.2.1 on 2024-02-10 09:59
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [
('jwt_auth', '0081_alter_cuserroleloginopt_uuid'),
]
operations = [
migrations.AlterField(
model_name='cuserroleloginopt',
name='uuid',
field=models.UUIDField(default=uuid.UUID('6537ef3d-8ef9-486d-a1b6-7892e021dc19'), unique=True),
),
]
@@ -0,0 +1,19 @@
# Generated by Django 4.2.1 on 2024-02-10 11:06
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [
('jwt_auth', '0082_alter_cuserroleloginopt_uuid'),
]
operations = [
migrations.AlterField(
model_name='cuserroleloginopt',
name='uuid',
field=models.UUIDField(default=uuid.UUID('745db968-c736-42cd-ad3d-4de41e8e5b98'), unique=True),
),
]
@@ -0,0 +1,19 @@
# Generated by Django 4.2.1 on 2024-02-18 09:44
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [
('jwt_auth', '0083_alter_cuserroleloginopt_uuid'),
]
operations = [
migrations.AlterField(
model_name='cuserroleloginopt',
name='uuid',
field=models.UUIDField(default=uuid.UUID('96211808-5203-451b-a6ce-eee394e02afc'), unique=True),
),
]
@@ -0,0 +1,19 @@
# Generated by Django 4.2.1 on 2024-02-27 09:59
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [
('jwt_auth', '0084_alter_cuserroleloginopt_uuid'),
]
operations = [
migrations.AlterField(
model_name='cuserroleloginopt',
name='uuid',
field=models.UUIDField(default=uuid.UUID('561d07a5-fff4-436f-bab3-4e3b16e05fba'), unique=True),
),
]
@@ -0,0 +1,19 @@
# Generated by Django 4.2.1 on 2024-04-16 06:28
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [
('jwt_auth', '0085_alter_cuserroleloginopt_uuid'),
]
operations = [
migrations.AlterField(
model_name='cuserroleloginopt',
name='uuid',
field=models.UUIDField(default=uuid.UUID('b5346fad-8d28-482d-8ed9-2807850b6a4d'), unique=True),
),
]
+24 -4
View File
@@ -5,14 +5,16 @@ from apps.jwt_auth.models import CUserRoleLoginOpt
from apps.cuser.models import CuserRole as CuserRoleModel, SmsOpt as SmsOptModel from apps.cuser.models import CuserRole as CuserRoleModel, SmsOpt as SmsOptModel
from django.utils import timezone from django.utils import timezone
from rest_framework import exceptions from rest_framework import exceptions
CUser = get_user_model() import requests
from datetime import timedelta
CUser = get_user_model()
def login_by_username(username: str, password: str) -> CUserRoleLoginOpt: def login_by_username(username: str, password: str) -> CUserRoleLoginOpt:
try: try:
print(username) print(username)
user = CUser.objects.get(username=username) user = CUser.objects.get(username=username)
print(user)
if user and user.check_password(password): if user and user.check_password(password):
cuser_roles = CuserRoleModel.objects.filter(cuser=user) cuser_roles = CuserRoleModel.objects.filter(cuser=user)
@@ -52,21 +54,35 @@ def login_by_mobile(mobile: int):
random_number = random.randint(100000, 999999) random_number = random.randint(100000, 999999)
try: try:
SmsOptModel.objects.filter(mobile=mobile).delete() SmsOptModel.objects.filter(mobile=mobile).delete()
except Exception as exp: except Exception as exp:
pass pass
opt_code = SmsOptModel(mobile=mobile, opt=123456) expire_time = timezone.now() + timedelta(minutes=3)
opt_code = SmsOptModel(mobile=mobile, opt=random_number, expire=expire_time)
opt_code.save() opt_code.save()
sms_text = f' کد ورود شما: {random_number}'
payload = {
'USERNAME': 'vsms7937',
'PASSWORD': '335577775533',
'FROM': '30005367',
'TO': int(mobile),
'TEXT': f'{sms_text}'
}
r = requests.get('http://www.0098sms.com/sendsmslink.aspx', params=payload)
except Exception as exp: except Exception as exp:
raise exceptions.ValidationError({'error': "mobile not found"}) raise exceptions.ValidationError({'error': "mobile not found"})
def verify_mobile_and_get_token(mobile: int, opt: int) -> CUserRoleLoginOpt: def verify_mobile_and_get_token(mobile: int, opt: int) -> CUserRoleLoginOpt:
try: try:
opt_obj = SmsOptModel.objects.filter(mobile=mobile, opt=opt)[0] time_now = timezone.now()
opt_obj = SmsOptModel.objects.filter(mobile=mobile, opt=opt, expire__gte=time_now)[0]
if opt_obj: if opt_obj:
cuser_roles = CuserRoleModel.objects.filter(cuser__mobile=mobile, is_active=True) cuser_roles = CuserRoleModel.objects.filter(cuser__mobile=mobile, is_active=True)
@@ -87,4 +103,8 @@ def verify_mobile_and_get_token(mobile: int, opt: int) -> CUserRoleLoginOpt:
SmsOptModel.objects.filter(mobile=mobile).delete() SmsOptModel.objects.filter(mobile=mobile).delete()
return login_opts return login_opts
except Exception as exp: except Exception as exp:
try:
SmsOptModel.objects.filter(mobile=mobile).delete()
except Exception as exp:
pass
raise exceptions.ValidationError({'error': "cannot verify this mobile and opt code:"+str(exp)}) raise exceptions.ValidationError({'error': "cannot verify this mobile and opt code:"+str(exp)})
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-02-10 09:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lead', '0035_alter_lead_status'),
]
operations = [
migrations.AlterField(
model_name='lead',
name='status',
field=models.CharField(blank=True, choices=[('SU', 'OK'), ('UN', 'unknown'), ('FA', 'FAIL')], default='UN', max_length=2, null=True),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-02-10 11:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lead', '0036_alter_lead_status'),
]
operations = [
migrations.AlterField(
model_name='lead',
name='status',
field=models.CharField(blank=True, choices=[('UN', 'unknown'), ('SU', 'OK'), ('FA', 'FAIL')], default='UN', max_length=2, null=True),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-02-18 09:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lead', '0037_alter_lead_status'),
]
operations = [
migrations.AlterField(
model_name='lead',
name='status',
field=models.CharField(blank=True, choices=[('FA', 'FAIL'), ('SU', 'OK'), ('UN', 'unknown')], default='UN', max_length=2, null=True),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-02-27 09:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lead', '0038_alter_lead_status'),
]
operations = [
migrations.AlterField(
model_name='lead',
name='status',
field=models.CharField(blank=True, choices=[('SU', 'OK'), ('UN', 'unknown'), ('FA', 'FAIL')], default='UN', max_length=2, null=True),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-04-16 06:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lead', '0039_alter_lead_status'),
]
operations = [
migrations.AlterField(
model_name='lead',
name='status',
field=models.CharField(blank=True, choices=[('FA', 'FAIL'), ('SU', 'OK'), ('UN', 'unknown')], default='UN', max_length=2, null=True),
),
]
+21 -3
View File
@@ -3,7 +3,7 @@ from apps.lead.models import Lead as LeadModel, LeadType as LeadTypeModel,\
from apps.shop.models import ProductType as ProductTypeModel from apps.shop.models import ProductType as ProductTypeModel
from apps.workspace.models import City as CityModel from apps.workspace.models import City as CityModel
from utils.get_user_workspace import get_user_workspace_uuid from utils.get_user_workspace import get_user_workspace_uuid
from utils.get_cuser_role import get_cuser_role_uuid from utils.get_cuser_role import get_cuser_role_uuid, get_cuser_role
from rest_framework import exceptions from rest_framework import exceptions
@@ -12,7 +12,16 @@ def list_leads(request) -> LeadModel:
try: try:
workspace_uuid = get_user_workspace_uuid(request) workspace_uuid = get_user_workspace_uuid(request)
cuser_role_uuid = get_cuser_role_uuid(request) cuser_role_uuid = get_cuser_role_uuid(request)
leads = LeadModel.objects.filter(sys_ws__uuid=workspace_uuid, cuser_role__uuid=cuser_role_uuid).order_by('-created_at') cuser_role = get_cuser_role(request)
base_filter = {
'sys_ws__uuid': workspace_uuid,
}
if not cuser_role.is_admin:
base_filter['cuser_role__uuid'] = cuser_role_uuid
leads = LeadModel.objects.filter(**base_filter).order_by('-created_at')
return leads return leads
except Exception as exp: except Exception as exp:
@@ -25,7 +34,16 @@ def retrieve_lead(request, id: int) -> LeadModel:
try: try:
workspace_uuid = get_user_workspace_uuid(request) workspace_uuid = get_user_workspace_uuid(request)
cuser_role_uuid = get_cuser_role_uuid(request) cuser_role_uuid = get_cuser_role_uuid(request)
lead = LeadModel.objects.get(id=id, sys_ws__uuid=workspace_uuid, cuser_role__uuid=cuser_role_uuid)
cuser_role = get_cuser_role(request)
base_filter = {
'sys_ws__uuid': workspace_uuid,
}
if not cuser_role.is_admin:
base_filter['cuser_role__uuid'] = cuser_role_uuid
lead = LeadModel.objects.get(id=id, **base_filter)
return lead return lead
except Exception as exp: except Exception as exp:
message = f'Error retrieve Leads: {exp}' message = f'Error retrieve Leads: {exp}'
+5
View File
@@ -139,6 +139,11 @@ class LeadListApi(ListAPIView):
'ostan': inline_serializer(many=False, fields={'name': serializers.CharField() }) 'ostan': inline_serializer(many=False, fields={'name': serializers.CharField() })
}) })
cuser_role = inline_serializer(many=False, fields={
'id': serializers.IntegerField(),
'name_family': serializers.CharField()
})
class Meta: class Meta:
model = LeadModel model = LeadModel
fields = '__all__' fields = '__all__'
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-02-10 09:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('reminder', '0029_alter_reminder_type'),
]
operations = [
migrations.AlterField(
model_name='reminder',
name='type',
field=models.CharField(choices=[('LE', 'LEAD'), ('NO', 'NOTE'), ('UN', 'UNKNOWN'), ('CU', 'CUSTOMER')], default='UN', max_length=2),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-02-10 11:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('reminder', '0030_alter_reminder_type'),
]
operations = [
migrations.AlterField(
model_name='reminder',
name='type',
field=models.CharField(choices=[('CU', 'CUSTOMER'), ('NO', 'NOTE'), ('LE', 'LEAD'), ('UN', 'UNKNOWN')], default='UN', max_length=2),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-02-18 09:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('reminder', '0031_alter_reminder_type'),
]
operations = [
migrations.AlterField(
model_name='reminder',
name='type',
field=models.CharField(choices=[('UN', 'UNKNOWN'), ('CU', 'CUSTOMER'), ('LE', 'LEAD'), ('NO', 'NOTE')], default='UN', max_length=2),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-02-27 09:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('reminder', '0032_alter_reminder_type'),
]
operations = [
migrations.AlterField(
model_name='reminder',
name='type',
field=models.CharField(choices=[('LE', 'LEAD'), ('UN', 'UNKNOWN'), ('CU', 'CUSTOMER'), ('NO', 'NOTE')], default='UN', max_length=2),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-04-16 06:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('reminder', '0033_alter_reminder_type'),
]
operations = [
migrations.AlterField(
model_name='reminder',
name='type',
field=models.CharField(choices=[('CU', 'CUSTOMER'), ('NO', 'NOTE'), ('UN', 'UNKNOWN'), ('LE', 'LEAD')], default='UN', max_length=2),
),
]
View File
Whitespace-only changes.
+41
View File
@@ -0,0 +1,41 @@
from apps.lead.models import Lead as LeadModel
from apps.cuser.models import CuserRole as CuserRoleModel, RoleType as RoleTypeModel
from rest_framework import serializers
from django.db.models import Count
from django.db.models import Count
from rest_framework import exceptions
def list_leads_api() -> LeadModel:
try:
base_filter = {
'sys_ws__uuid': 'ca918836-ddf2-4d88-8d76-033d285062e4',
}
leads = LeadModel.objects.filter(**base_filter).order_by('-created_at')
return leads
except Exception as exp:
message = f'Error Fetching List Leads: {exp}'
raise exceptions.ValidationError({'error': message})
def user_lead_report_count_by_date(start_datetime, end_datetime, status: str | None = None,):
base_filer = {
'cuser_role__role_type__role_name_en': 'workspace_operator',
'created_at__range': [start_datetime, end_datetime],
}
if status:
base_filer['status'] = status
return LeadModel.objects.filter(**base_filer).values('cuser_role__name_family').annotate(
count=Count('cuser_role__name_family')).order_by('-count')
def operators_cuser_role():
return CuserRoleModel.objects.filter(sys_ws_id=2, role_type__role_name_en='workspace_operator')
+1
View File
@@ -0,0 +1 @@
+8
View File
@@ -0,0 +1,8 @@
from django.urls import path
from apps.report.views import ReportApiView, LeadListApi
urlpatterns = [
path('lead/', ReportApiView.as_view(), name='report-lead'),
path('lead/list/loolegostar-x89i20/', LeadListApi.as_view(), name='report-lead'),
]
+115
View File
@@ -0,0 +1,115 @@
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import serializers
from rest_framework.generics import ListAPIView
from rest_framework.views import APIView
from apps.lead.models import Lead as LeadModel
from rest_framework.response import Response
from rest_framework import status
from apps.report.selector import user_lead_report_count_by_date
from apps.cuser.models import CuserRole as CuserRoleModel
from datetime import datetime
from apps.report.selector import list_leads_api
from utils.pagination import CustomPagination
from utils.tools import inline_serializer
class ReportApiView(APIView):
class ResultSerializer(serializers.Serializer):
class OperatorSerializer(serializers.Serializer):
cuser_role__name_family = serializers.CharField()
count = serializers.IntegerField()
su = OperatorSerializer(many=True)
un = OperatorSerializer(many=True)
fa = OperatorSerializer(many=True)
all = OperatorSerializer(many=True)
def get(self, request):
date_format = "%Y-%m-%d"
start_datetime = request.query_params.get('start_datetime', None)
if start_datetime:
start_datetime = start_datetime.replace(" ", "")
end_datetime = request.query_params.get('end_datetime', None)
if end_datetime:
end_datetime = end_datetime.replace(" ", "")
#example start_datetime : 2024-03-20T14:31:16 03:30
if start_datetime and end_datetime:
start_dt = datetime.strptime(start_datetime, date_format)
end_dt = datetime.strptime(end_datetime, date_format)
else:
start_dt = datetime.now()
end_dt = datetime.now()
# status = request.query_params.get('status')
#همه
users_all_lead_count = user_lead_report_count_by_date(start_datetime=start_dt, end_datetime=end_dt)
#موفق
users_su_lead_count = user_lead_report_count_by_date(status='SU', start_datetime=start_dt, end_datetime=end_dt)
#شکست
users_fa_lead_count = user_lead_report_count_by_date(status='FA', start_datetime=start_dt, end_datetime=end_dt)
#نا معلوم
users_un_lead_count = user_lead_report_count_by_date(status='UN', start_datetime=start_dt, end_datetime=end_dt)
result = {
'su': users_su_lead_count,
'fa': users_fa_lead_count,
'un': users_un_lead_count,
'all': users_all_lead_count,
}
output_serializer = self.ResultSerializer(result)
return Response(output_serializer.data)
class LeadListApi(ListAPIView):
#permission_classes = (IsAuthenticated, custom_permissions.WorkspaceOperatorPermission)
class Pagination(CustomPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 20
class OutputSerializer(serializers.ModelSerializer):
customer = inline_serializer(many=False, fields={'name_family': serializers.CharField(), })
product_type = inline_serializer(many=False, fields={'name': serializers.CharField(), })
type = inline_serializer(many=False, fields={'title': serializers.CharField(), })
source = inline_serializer(many=False, fields={'title': serializers.CharField(), })
step = inline_serializer(many=False, fields={
'id': serializers.IntegerField(),
'name': serializers.CharField(),
})
city = inline_serializer(many=False, fields={
'name': serializers.CharField(),
'ostan': inline_serializer(many=False, fields={'name': serializers.CharField() })
})
cuser_role = inline_serializer(many=False, fields={
'id': serializers.IntegerField(),
'name_family': serializers.CharField()
})
class Meta:
model = LeadModel
fields = '__all__'
serializer_class = OutputSerializer
pagination_class = Pagination
filter_backends = [DjangoFilterBackend]
filterset_fields = ['step', 'status', ]
def get_queryset(self):
return list_leads_api()
+1 -1
View File
@@ -22,7 +22,7 @@ class ProductCategoryAdmin(admin.ModelAdmin):
@admin.register(ProductModel) @admin.register(ProductModel)
class ProductAdmin(admin.ModelAdmin): class ProductAdmin(admin.ModelAdmin):
pass search_fields = ("name", "category__name", "acc_code")
@admin.register(OrderModel) @admin.register(OrderModel)
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-02-27 09:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('shop', '0019_alter_product_price'),
]
operations = [
migrations.AddField(
model_name='product',
name='view_only',
field=models.BooleanField(blank=True, default=False, null=True),
),
]
+1
View File
@@ -34,6 +34,7 @@ class Product(BaseModel):
acc_code = models.CharField(null=True, blank=True) acc_code = models.CharField(null=True, blank=True)
order_prd = models.PositiveIntegerField(null=True, blank=True, default=None) order_prd = models.PositiveIntegerField(null=True, blank=True, default=None)
attr = models.JSONField(null=True, blank=True) attr = models.JSONField(null=True, blank=True)
view_only = models.BooleanField(null=True, blank=True, default=False)
sys_ws = models.ForeignKey(WorkspaceModel, on_delete=models.CASCADE, null=False, blank=False) sys_ws = models.ForeignKey(WorkspaceModel, on_delete=models.CASCADE, null=False, blank=False)
+23 -6
View File
@@ -55,11 +55,18 @@ def list_order_operators(request) -> OrderModel:
try: try:
workspace_uuid = get_user_workspace_uuid(request) workspace_uuid = get_user_workspace_uuid(request)
cuser_role_uuid = get_cuser_role_uuid(request) cuser_role_uuid = get_cuser_role_uuid(request)
cuser_role = get_cuser_role(request)
customer_responsibles = CustomerResponsibleModel.objects.filter(cuser_role__uuid=cuser_role_uuid, sys_ws__uuid=workspace_uuid) customer_responsibles = CustomerResponsibleModel.objects.filter(cuser_role__uuid=cuser_role_uuid, sys_ws__uuid=workspace_uuid)
responsible_group_ids = customer_responsibles.values_list('responsible_group__id', flat=True) responsible_group_ids = customer_responsibles.values_list('responsible_group__id', flat=True)
orders = OrderModel.objects.filter(sys_ws__uuid=workspace_uuid, base_filter = {
responsible_group_id__in=responsible_group_ids).order_by('-created_at')[:10] 'sys_ws__uuid': workspace_uuid,
}
if not cuser_role.is_admin:
base_filter['responsible_group_id__in'] = responsible_group_ids
orders = OrderModel.objects.filter(**base_filter).order_by('-created_at')[:50]
return orders return orders
except Exception as exp: except Exception as exp:
message = f'Error Fetching List Order: {exp}' message = f'Error Fetching List Order: {exp}'
@@ -70,13 +77,23 @@ def retrieve_order_operators(request, order_id) -> OrderModel:
try: try:
workspace_uuid = get_user_workspace_uuid(request) workspace_uuid = get_user_workspace_uuid(request)
cuser_role_uuid = get_cuser_role_uuid(request) cuser_role_uuid = get_cuser_role_uuid(request)
cuser_role = get_cuser_role(request)
customer_responsibles = CustomerResponsibleModel.objects.filter(cuser_role__uuid=cuser_role_uuid, sys_ws__uuid=workspace_uuid) customer_responsibles = CustomerResponsibleModel.objects.filter(cuser_role__uuid=cuser_role_uuid, sys_ws__uuid=workspace_uuid)
responsible_group_ids = customer_responsibles.values_list('responsible_group__id', flat=True) responsible_group_ids = customer_responsibles.values_list('responsible_group__id', flat=True)
order = OrderModel.objects.get(id=order_id, sys_ws__uuid=workspace_uuid, base_filter = {
responsible_group_id__in=responsible_group_ids) 'sys_ws__uuid': workspace_uuid,
order.view_at = timezone.now() 'id': order_id,
order.save() }
if not cuser_role.is_admin:
base_filter['responsible_group_id__in'] = responsible_group_ids
order = OrderModel.objects.get(**base_filter)
if not cuser_role.is_admin:
order.view_at = timezone.now()
order.save()
return order return order
except Exception as exp: except Exception as exp:
+12 -1
View File
@@ -22,13 +22,24 @@ def list_product(workspace_uuid: str) -> ProductModel:
def list_product_by_category(workspace_uuid: str, category_id: int) -> ProductModel: def list_product_by_category(workspace_uuid: str, category_id: int) -> ProductModel:
try: try:
product_category_obj = ProductModel.objects.filter(sys_ws__uuid=workspace_uuid, category_id=category_id) product_category_obj = ProductModel.objects.filter(sys_ws__uuid=workspace_uuid, category_id=category_id,
view_only=False)
return product_category_obj return product_category_obj
except Exception as exp: except Exception as exp:
message = f'Error Fetching List Product by category: {exp}' message = f'Error Fetching List Product by category: {exp}'
raise exceptions.ValidationError({'error': message}) raise exceptions.ValidationError({'error': message})
def list_view_only_product_by_category(workspace_uuid: str, category_id: int) -> ProductModel:
try:
view_only_product_category_obj = ProductModel.objects.filter(sys_ws__uuid=workspace_uuid, category_id=category_id,
view_only=True)
return view_only_product_category_obj
except Exception as exp:
message = f'Error Fetching View Only List Product by category: {exp}'
raise exceptions.ValidationError({'error': message})
def count_product_in_category(workspace_uuid: str, category_id: int) -> int: def count_product_in_category(workspace_uuid: str, category_id: int) -> int:
try: try:
count_product = ProductModel.objects.filter(sys_ws__uuid=workspace_uuid, category_id=category_id).count() count_product = ProductModel.objects.filter(sys_ws__uuid=workspace_uuid, category_id=category_id).count()
+3 -1
View File
@@ -34,5 +34,7 @@ urlpatterns = [
path('cart/add/', CartCreateApi.as_view(), name='add_cart'), path('cart/add/', CartCreateApi.as_view(), name='add_cart'),
path('cart/delete/<int:cart_id>/', CartDeleteApi.as_view(), name='delete_cart'), path('cart/delete/<int:cart_id>/', CartDeleteApi.as_view(), name='delete_cart'),
#path('import/', ImportExcelView.as_view(), name='import_excel'), path('import/', ImportExcelView.as_view(), name='import_excel'),
path('import/customer/', ImportExcelCustomersView.as_view(), name='import_excel_customer'),
#path('import/city/', ImportExcelCitysView.as_view(), name='import_excel_city'),
] ]
+1 -1
View File
@@ -16,4 +16,4 @@ from .cart import (CartListApi, CartCreateApi, CartDeleteApi)
from .order_item import (OrderItemsListApi, ) from .order_item import (OrderItemsListApi, )
from .excel_import import ImportExcelView from .excel_import import ImportExcelView, ImportExcelCitysView, ImportExcelCustomersView
+90 -15
View File
@@ -2,7 +2,9 @@ from rest_framework.views import APIView
from rest_framework.response import Response from rest_framework.response import Response
import pandas as pd import pandas as pd
from apps.shop.models import Product as ProductModel, ProductCategory as ProductCategoryModel from apps.shop.models import Product as ProductModel, ProductCategory as ProductCategoryModel
from apps.workspace.models import Workspace as WorkspaceModel from apps.workspace.models import Workspace as WorkspaceModel, City as CityModel
from apps.customer.models import Customer as CustomerModel
from apps.customer.models import ResponsibleGroup as ResponsibleGroupModel
import os import os
@@ -13,27 +15,100 @@ class ImportExcelView(APIView):
df = pd.read_excel('pe.xlsx') df = pd.read_excel('pe.xlsx')
for index, row in df.iterrows(): for index, row in df.iterrows():
cate_name = row['cate_name'] cate_name = row['cate_name']
order_cat = row['order_cat'] #order_cat = row['order_cat']
acc_code = row['acc_code'] acc_code = row['acc_code']
prd_name = row['prd_name'] prd_name = row['name']
order_prd = row['order_prd'] order_prd = row['size']
vahed = row['vahed'] vahed = row['vahed']
workspace = WorkspaceModel.objects.get(id=2) workspace = WorkspaceModel.objects.get(id=2)
try: try:
prd_ct = ProductCategoryModel.objects.get(name=cate_name, sys_ws=workspace, order_cat=order_cat) prd_ct = ProductCategoryModel.objects.get(name=cate_name, sys_ws=workspace)
except ProductCategoryModel.DoesNotExist as exp: except ProductCategoryModel.DoesNotExist as exp:
prd_ct = ProductCategoryModel.objects.create(name=cate_name, sys_ws=workspace, order_cat=order_cat) prd_ct = ProductCategoryModel.objects.create(name=cate_name, sys_ws=workspace)
new_product = ProductModel() if ProductModel.objects.filter(acc_code=acc_code).exists() == False:
new_product.name = prd_name new_product = ProductModel()
new_product.price = 0 new_product.name = prd_name
new_product.category = ProductCategoryModel.objects.get(id=prd_ct.id) new_product.price = 0
new_product.acc_code = acc_code new_product.category = ProductCategoryModel.objects.get(id=prd_ct.id)
new_product.order_prd = order_prd new_product.acc_code = acc_code
new_product.attr = {"acc_vahed": vahed} new_product.order_prd = order_prd
new_product.sys_ws = workspace new_product.view_only = True
new_product.save() new_product.attr = {"acc_vahed": vahed}
new_product.sys_ws = workspace
new_product.save()
else:
up_product = ProductModel.objects.get(acc_code=acc_code)
up_product.name = prd_name
up_product.save()
return Response(data={"result": 'ok'}) return Response(data={"result": 'ok'})
class ImportExcelCitysView(APIView):
def get(self, request):
df = pd.read_excel('cities.xlsx')
for index, row in df.iterrows():
city_name = row['name']
pv_id = row['province_id']
try:
ostan = CityModel.objects.get(pv_id=pv_id, is_ostan=True)
except Exception as exp:
print(city_name)
print(pv_id)
city_obj = CityModel()
city_obj.name = city_name
city_obj.is_ostan = False
city_obj.ostan = ostan
city_obj.save()
return Response(data={"result": 'ok'})
class ImportExcelCustomersView(APIView):
def get(self, request):
df = pd.read_excel('customersData.xlsx')
for index, row in df.iterrows():
name = row['name']
mobile = row['mobile']
if name and mobile:
phone = row['phone']
address = row['address']
ostan = row['ostan']
shahr = row['shar']
mantaghe = row['id_mantaghe']
try:
ostan_obj = CityModel.objects.get(name=ostan, is_ostan=True)
shahr_obj = CityModel.objects.get(name=shahr, ostan=ostan_obj)
except Exception as exp:
shahr_obj = CityModel.objects.get(id=1229)
try:
cs = CustomerModel()
cs.name_family = name
cs.mobile = mobile
if phone:
cs.phone = phone
cs.city = shahr_obj
if address:
cs.address = address
cs.responsible_group = ResponsibleGroupModel.objects.get(id=mantaghe)
cs.sys_ws = WorkspaceModel.objects.get(id=2)
cs.save()
except Exception as exp:
print(name)
return Response(data={"result": 'ok'})
+5 -2
View File
@@ -124,7 +124,7 @@ class OrderUpdateApi(APIView):
class OrderDeleteApi(APIView): class OrderDeleteApi(APIView):
permission_classes = (IsAuthenticated,)
def delete(self, request, order_id: int): def delete(self, request, order_id: int):
user_workspace_uuid = get_user_workspace_uuid(request=request) user_workspace_uuid = get_user_workspace_uuid(request=request)
@@ -139,7 +139,7 @@ class OrderDeleteApi(APIView):
class OrderListApi(generics.ListAPIView): class OrderListApi(generics.ListAPIView):
permission_classes = (IsAuthenticated,)
class OutputSerializer(serializers.ModelSerializer): class OutputSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = OrderModel model = OrderModel
@@ -155,6 +155,7 @@ class OrderListApi(generics.ListAPIView):
class OrderListOperatorApi(generics.ListAPIView): class OrderListOperatorApi(generics.ListAPIView):
permission_classes = (IsAuthenticated,)
class OutputSerializer(serializers.ModelSerializer): class OutputSerializer(serializers.ModelSerializer):
customer = inline_serializer(fields={ customer = inline_serializer(fields={
'id': serializers.IntegerField(), 'id': serializers.IntegerField(),
@@ -172,6 +173,7 @@ class OrderListOperatorApi(generics.ListAPIView):
class OrderRetrieveOperatorApi(APIView): class OrderRetrieveOperatorApi(APIView):
permission_classes = (IsAuthenticated,)
class OutputSerializer(serializers.ModelSerializer): class OutputSerializer(serializers.ModelSerializer):
customer = inline_serializer(fields={ customer = inline_serializer(fields={
@@ -210,6 +212,7 @@ class OrderRetrieveOperatorApi(APIView):
class OrderRetrieveOperatorExcelApi(APIView): class OrderRetrieveOperatorExcelApi(APIView):
permission_classes = (IsAuthenticated, )
def get(self, request, order_id): def get(self, request, order_id):
order_df = retrieve_order_item_excel(request=request, order_id=order_id) order_df = retrieve_order_item_excel(request=request, order_id=order_id)
+9 -1
View File
@@ -134,6 +134,7 @@ class ProductListCategoryApi(generics.ListAPIView):
id = serializers.IntegerField() id = serializers.IntegerField()
name = serializers.CharField() name = serializers.CharField()
price = serializers.FloatField() price = serializers.FloatField()
view_only = serializers.BooleanField()
class Meta: class Meta:
exclude = ('sys_ws', ) exclude = ('sys_ws', )
@@ -144,6 +145,8 @@ class ProductListCategoryApi(generics.ListAPIView):
serializer = self.get_serializer(queryset_data, many=True) serializer = self.get_serializer(queryset_data, many=True)
workspace_uuid = get_user_workspace_uuid(request=request) workspace_uuid = get_user_workspace_uuid(request=request)
category = retrieve_product_category(category_id=category_id, workspace_uuid=workspace_uuid) category = retrieve_product_category(category_id=category_id, workspace_uuid=workspace_uuid)
view_only_products = list_view_only_product_by_category(category_id=category_id, workspace_uuid=workspace_uuid)
view_only_products_serializer = self.get_serializer(view_only_products, many=True)
if len(serializer.data) == 0: if len(serializer.data) == 0:
return Response( return Response(
@@ -152,9 +155,14 @@ class ProductListCategoryApi(generics.ListAPIView):
data = { data = {
"category_name": category.name, "category_name": category.name,
"category_img": category.image.url, "category_img": category.image.url,
"products": serializer.data "products": serializer.data,
} }
if len(view_only_products_serializer.data) >=1:
data['view_only_products'] = view_only_products_serializer.data
else:
data['view_only_products'] = None
return Response(data) return Response(data)
def get_queryset(self): def get_queryset(self):
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-02-10 09:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('workspace', '0013_alter_workspace_cuser_owner'),
]
operations = [
migrations.AddField(
model_name='city',
name='pv_id',
field=models.PositiveSmallIntegerField(blank=True, null=True),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.2.1 on 2024-02-10 11:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('workspace', '0014_city_pv_id'),
]
operations = [
migrations.AlterField(
model_name='city',
name='name',
field=models.CharField(blank=True, max_length=30, null=True),
),
]
@@ -0,0 +1,17 @@
# Generated by Django 4.2.1 on 2024-02-18 09:44
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('workspace', '0015_alter_city_name'),
]
operations = [
migrations.RemoveField(
model_name='workspace',
name='cuser_owner',
),
]
+3 -2
View File
@@ -11,7 +11,7 @@ class Workspace(BaseModel):
#cuser_role_owner = models.OneToOneField(CuserRoleModel, on_delete=models.CASCADE, #cuser_role_owner = models.OneToOneField(CuserRoleModel, on_delete=models.CASCADE,
# related_name='workspace', null=True, blank=True) # related_name='workspace', null=True, blank=True)
cuser_owner = models.ForeignKey(CUser, on_delete=models.SET_NULL, null=True, blank=True, default=None) #cuser_owner = models.ForeignKey(CUser, on_delete=models.SET_NULL, null=True, blank=True, default=None)
name = models.CharField(max_length=15, null=False, blank=False) name = models.CharField(max_length=15, null=False, blank=False)
username = models.CharField(max_length=30, null=False, blank=False, unique=True) username = models.CharField(max_length=30, null=False, blank=False, unique=True)
expire = models.DateTimeField(null=True, blank=True) expire = models.DateTimeField(null=True, blank=True)
@@ -27,9 +27,10 @@ class Workspace(BaseModel):
class City(BaseModel): class City(BaseModel):
name = models.CharField(max_length=15, null=True, blank=True) name = models.CharField(max_length=30, null=True, blank=True)
is_ostan = models.BooleanField(default=False, null=False, blank=False) is_ostan = models.BooleanField(default=False, null=False, blank=False)
ostan = models.ForeignKey('self', models.CASCADE, null=True, blank=True) ostan = models.ForeignKey('self', models.CASCADE, null=True, blank=True)
pv_id = models.PositiveSmallIntegerField(null=True, blank=True)
def __str__(self): def __str__(self):
return str(self.name) return str(self.name)
+1 -1
View File
@@ -11,6 +11,6 @@ import os
from django.core.asgi import get_asgi_application from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'crmApi.settings') os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
application = get_asgi_application() application = get_asgi_application()
+14 -2
View File
@@ -19,8 +19,6 @@ BASE_DIR = Path(__file__).resolve().parent.parent
MEDIA_URL = '/media/' MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR.parent /'media' MEDIA_ROOT = BASE_DIR.parent /'media'
print(MEDIA_ROOT)
# Quick-start development settings - unsuitable for production # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
@@ -33,8 +31,22 @@ DEBUG = True
ALLOWED_HOSTS = ['*'] ALLOWED_HOSTS = ['*']
CORS_ALLOWED_ORIGINS = [ CORS_ALLOWED_ORIGINS = [
"http://192.168.138.94:3000",
"http://192.168.138.94:3001",
"http://localhost:3001", "http://localhost:3001",
"http://localhost:3002",
"http://localhost:3000", "http://localhost:3000",
"https://loolegostar.liara.run",
"https://loolegostar-crm.liara.run",
]
CORS_ALLOW_METHODS = [
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
] ]
AUTH_USER_MODEL = 'cuser.CUser' AUTH_USER_MODEL = 'cuser.CUser'
+11
View File
@@ -1 +1,12 @@
from .base import * from .base import *
DEBUG = False
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'crm-api',
'USER': 'root',
'PASSWORD': '1yI0Iw2Fpjm2BXhEnwUKVdDg',
'HOST': 'loolegostar-db',
'PORT': '5432'
}
}
+1
View File
@@ -23,6 +23,7 @@ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('auth/', include('apps.jwt_auth.urls')), path('auth/', include('apps.jwt_auth.urls')),
path('cuser/', include('apps.cuser.urls')), path('cuser/', include('apps.cuser.urls')),
path('report/', include('apps.report.urls')),
path('customer/', include('apps.customer.urls')), path('customer/', include('apps.customer.urls')),
path('shop/', include('apps.shop.urls')), path('shop/', include('apps.shop.urls')),
path('ticket/', include('apps.ticket.urls')), path('ticket/', include('apps.ticket.urls')),
+1 -1
View File
@@ -11,6 +11,6 @@ import os
from django.core.wsgi import get_wsgi_application from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'crmApi.settings') os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
application = get_wsgi_application() application = get_wsgi_application()
+10
View File
@@ -0,0 +1,10 @@
{
"platform": "django",
"app": "loolegostar-api",
"disks": [
{
"name": "media",
"mountTo": "media"
}
]
}
+29
View File
@@ -0,0 +1,29 @@
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
client_max_body_size 250M;
location /media {
alias /usr/src/app/media;
}
location /static {
alias /usr/src/app/config/staticfiles;
}
location / {
try_files /dev/null @django_app;
}
location ~\.sqlite3$ {
deny all;
error_page 403 =404 /;
}
location ~ /\.well-known {
allow all;
}
+14
View File
@@ -0,0 +1,14 @@
Django==4.2.1
djangorestframework==3.14.0
Markdown==3.4.3
requests==2.31.0
django-filter==23.2
drf-spectacular==0.26.2
psycopg==3.1.9
psycopg-binary==3.1.9
djangorestframework-simplejwt==5.2.2
django-cors-headers==4.3.1
openpyxl==3.1.2
XlsxWriter==3.1.9
pandas==2.2.0
pillow==10.2.0
+2
View File
@@ -1,9 +1,11 @@
Django==4.2.1 Django==4.2.1
djangorestframework==3.14.0 djangorestframework==3.14.0
Markdown==3.4.3 Markdown==3.4.3
requests==2.31.0
django-filter==23.2 django-filter==23.2
drf-spectacular==0.26.2 drf-spectacular==0.26.2
psycopg==3.1.9 psycopg==3.1.9
psycopg-binary==3.1.9
djangorestframework-simplejwt==5.2.2 djangorestframework-simplejwt==5.2.2
django-cors-headers==4.3.1 django-cors-headers==4.3.1
openpyxl==3.1.2 openpyxl==3.1.2