init commit

This commit is contained in:
Ali Arya 2025-05-05 17:50:36 +03:30
commit 567fd46741
784 changed files with 63724 additions and 0 deletions

94
.gitignore vendored Normal file
View File

@ -0,0 +1,94 @@
# Created by https://www.gitignore.io
### OSX ###
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml
# Translations
*.mo
*.pot
# Sphinx documentation
docs/_build/
# PyBuilder
target/
### Django ###
*.log
*.pot
*.pyc
__pycache__/
local_settings.py
.env
venv
db.sqlite3
iralex
storage

48
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,48 @@
# This file is a template, and might need editing before it works on your project.
# This is a sample GitLab CI/CD configuration file that should run without any modifications.
# It demonstrates a basic 3 stage CI/CD pipeline. Instead of real tests or scripts,
# it uses echo commands to simulate the pipeline execution.
#
# A pipeline is composed of independent jobs that run scripts, grouped into stages.
# Stages run in sequential order, but jobs within stages run in parallel.
#
# For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages
#
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml
stages: # List of stages for jobs, and their order of execution
- build
- test
- deploy
build-job: # This job runs in the build stage, which runs first.
script: echo 'this should run on pull requests'
only:
- https://gitlab.com/yo3ef.amini/iralex-backend
unit-test-job: # This job runs in the test stage.
stage: test # It only starts when the job in the build stage completes successfully.
script:
- echo "Running unit tests... This will take about 60 seconds."
- sleep 60
- echo "Code coverage is 90%"
lint-test-job: # This job also runs in the test stage.
stage: test # It can run at the same time as unit-test-job (in parallel).
script:
- echo "Linting code... This will take about 10 seconds."
- sleep 10
- echo "No lint issues found."
deploy-job: # This job runs in the deploy stage.
stage: deploy # It only runs when *both* jobs in the test stage complete successfully.
environment: production
script:
- echo "Deploying application..."
- echo "Application successfully deployed."

2
.htaccess Normal file
View File

@ -0,0 +1,2 @@
Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT"

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

14
.idea/dataSources.xml Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="Django default" uuid="d1ff0dae-7faf-4db7-9477-d34e07ee1dd1">
<driver-ref>postgresql</driver-ref>
<synchronize>true</synchronize>
<imported>true</imported>
<remarks>$PROJECT_DIR$/detective_book/settings.py</remarks>
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
<jdbc-url>jdbc:postgresql://ira-lex.postgres.database.azure.com:5432/iralex</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

View File

@ -0,0 +1,67 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<Languages>
<language minSize="107" name="Python" />
</Languages>
</inspection_tool>
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="32">
<item index="0" class="java.lang.String" itemvalue="httpx" />
<item index="1" class="java.lang.String" itemvalue="motor" />
<item index="2" class="java.lang.String" itemvalue="PyJWT" />
<item index="3" class="java.lang.String" itemvalue="cffi" />
<item index="4" class="java.lang.String" itemvalue="h11" />
<item index="5" class="java.lang.String" itemvalue="pycparser" />
<item index="6" class="java.lang.String" itemvalue="requests" />
<item index="7" class="java.lang.String" itemvalue="rfc3986" />
<item index="8" class="java.lang.String" itemvalue="sniffio" />
<item index="9" class="java.lang.String" itemvalue="starlette" />
<item index="10" class="java.lang.String" itemvalue="certifi" />
<item index="11" class="java.lang.String" itemvalue="anyio" />
<item index="12" class="java.lang.String" itemvalue="urllib3" />
<item index="13" class="java.lang.String" itemvalue="uvicorn" />
<item index="14" class="java.lang.String" itemvalue="passlib" />
<item index="15" class="java.lang.String" itemvalue="pydantic" />
<item index="16" class="java.lang.String" itemvalue="pymongo" />
<item index="17" class="java.lang.String" itemvalue="six" />
<item index="18" class="java.lang.String" itemvalue="asgiref" />
<item index="19" class="java.lang.String" itemvalue="python-multipart" />
<item index="20" class="java.lang.String" itemvalue="click" />
<item index="21" class="java.lang.String" itemvalue="bcrypt" />
<item index="22" class="java.lang.String" itemvalue="fastapi" />
<item index="23" class="java.lang.String" itemvalue="colorama" />
<item index="24" class="java.lang.String" itemvalue="typing_extensions" />
<item index="25" class="java.lang.String" itemvalue="charset-normalizer" />
<item index="26" class="java.lang.String" itemvalue="python-decouple" />
<item index="27" class="java.lang.String" itemvalue="pytz" />
<item index="28" class="java.lang.String" itemvalue="httpcore" />
<item index="29" class="java.lang.String" itemvalue="idna" />
<item index="30" class="java.lang.String" itemvalue="weasyprint" />
<item index="31" class="java.lang.String" itemvalue="pydyf" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="N802" />
<option value="N812" />
</list>
</option>
</inspection_tool>
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredIdentifiers">
<list>
<option value="pymongo.results.UpdateResult.__await__" />
<option value="bool.*" />
</list>
</option>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

30
.idea/iralex-backend.iml Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="FacetManager">
<facet type="django" name="Django">
<configuration>
<option name="rootFolder" value="$MODULE_DIR$" />
<option name="settingsModule" value="detective_book/settings.py" />
<option name="manageScript" value="$MODULE_DIR$/manage.py" />
<option name="environment" value="&lt;map/&gt;" />
<option name="doNotUseTestRunner" value="false" />
<option name="trackFilePattern" value="migrations" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Django Lib" level="project" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
<component name="TemplatesService">
<option name="TEMPLATE_CONFIGURATION" value="Django" />
</component>
</module>

View File

@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="Django Lib">
<CLASSES>
<root url="file://$PROJECT_DIR$/venv/Lib/site-packages" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

4
.idea/misc.xml Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (iralex-backend)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/iralex-backend.iml" filepath="$PROJECT_DIR$/.idea/iralex-backend.iml" />
</modules>
</component>
</project>

6
.idea/other.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PySciProjectComponent">
<option name="PY_SCI_VIEW_SUGGESTED" value="true" />
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

9
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
"editor.tabSize": 4,
"editor.useTabStops": true,
"editor.insertSpaces": true,
"cSpell.enabledLanguageIds": [
"COBOL",
"ACUCOBOL"
]
}

48
1.json Normal file
View File

@ -0,0 +1,48 @@
{
"notifications": {
"is_new_calender_in_email": false,
"is_new_calender_in_app": false,
"is_new_calender_in_mobile": false,
"is_update_calender_in_app": false,
"is_update_calender_in_mobile": false,
"is_delete_calender_in_app": true,
"is_delete_calender_in_mobile": true,
"is_document_in_email": true,
"is_document_in_app": true,
"is_document_in_mobile": true,
"is_matter_Subscribed_in_app": true,
"is_matter_Subscribed_in_mobile": true,
"is_matter_status_in_app": true,
"is_matter_status_in_mobile": true,
"is_delete_matter_in_app": true,
"is_delete_matter_in_mobile": true,
"is_update_matter_in_email": true,
"is_update_matter_in_app": true,
"is_update_matter_in_mobile": true,
"is_note_subscribed_in_app": true,
"is_note_subscribed_in_mobile": true,
"is_update_note_in_app": true,
"is_update_note_in_mobile": true,
"is_delete_note_in_app": true,
"is_deleted_note_in_mobile": true,
"is_phone_log_subscribed_in_app": true,
"is_phone_log_subscribed_in_mobile": true,
"is_update_phone_log_in_app": true,
"is_update_phone_log_in_mobile": true,
"is_delete_phone_log_in_app": true,
"is_delete_phone_log_in_mobile": true,
"is_secure_message_in_email": true,
"is_task_in_email": true,
"is_task_in_app": true,
"is_task_in_mobile": true,
"is_update_task_in_email": true,
"is_update_task_in_app": true,
"is_update_task_in_mobile": true,
"is_deleted_task_in_email": true,
"is_deleted_task_in_app": true,
"is_mobile_task_in_mobile": true,
"is_complete_task_in_email": true,
"is_complete_task_in_app": true,
"is_complete_task_in_mobile": true
}
}

27
Iralex.pem Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA4xwH1WNhrDVfW7AavFcUeaVg7nGOyZqympKBn+mR1LbtD4Sc
lOxZHP7zRiBsIzsqotz8qcU64opnoZjvvK9VdysQYOeGnrj6X/mc2y5iPPH/RSce
gU9ErF2abG7WJ9podCnhATtr9Fh7H2jEp8XW7z+muHaD6uy+SQ3cIACuSWQU+rnR
+0N2mHOZqSCeQubGkuY+awsNOwTG9WiRRPkZqxbUbfT5ZB18WsHRkXsAnKhoPYiU
aH60R2M4mHNeeTqofbkuv7fXYpAeSHzzFEP+mas9BDEoOCA0oP4/xLMPcGA3HwIP
ew4NbK4pPScmiULWOJsqNZeXIgfz5zhmWwEpeQIDAQABAoIBAEnmHBJuVSDg+Rdv
lTOFrk7q5kCQSOMG6GjtlSpAqUgrAbZT81NuGI0b1HMUJ7vLC9OUzs47NC701EW7
6v5dmxS8uYaer6pEDIxgP47+Z87m+6Y31XBEJ9diWdZAtoSfR+/MlL9+42DNzbpp
r9vbv1V4Q7qwLbqqsDw7O05ailusjRfBN4x0wP7X63Pzb6SAfafA7QcGKC27Og5o
2H2XyWHj5a//DWac1eTn+T7HB+8/f7BhxIy9at6xC8xBM1A9gTulaWg64hP6Rxi2
BziPwWMogwUSIGhmM4uUI01cdIr89wJn6OAn0odp/3LWZnW+J0w5P2PvbEBtnTUF
lftKh+UCgYEA/i9hrqf5ZOitVivtQOuCt5AYjxGcRjt+Pf11nidExkz0937/LPMn
sG32+VDzAcfOfAGKvbpAk2q8nGV6q1gOFR/71UEzu+Ff92m6pKyue2okCFKx6HwK
N+yqGQ6l6tw0KfEksOIoidAhKauZsOWxkVQDOiuEPIBY7v/djCo1vjcCgYEA5Lso
gwGzqz5RtN/5/8P70e2bszcoOS0UFbpXlg/6zjQczVczMqQlMm+lIt08tJplLY2k
WC5ef2jXtBW3ULveZTr3YS53HVrjjIzNLu7pxiMIUGrMuLMcby8LYVYHW5dJheTU
RD8FY+2l6/Ry8xklYepu6QbDuYS3zIi5cv/w/c8CgYBCQKNbXNj6XlNf1I9AjqJB
qkNcdyCehb8/9SKFGIMqlMB9ChME6lP7/o2TKnBMlIHTfKtnDHbsdbO3qBOzOX5i
LzX6vcX4QKQ83sgRSBkqfd3qdXN9v2cCcKNdaJ4Ce2b1T69ak3gxg5hBPkMPAq+n
y5gTv2f2RRXpJbPfZtkfPQKBgAh/l7K+ZnGPYDPLOpuxKXMUU/ulqf3t2dgw0z5F
G7l7oDJU8hcImEU2drlD5RSExAucPqX0Gxi6yYDsaaI7SLkUJsrakhxqGxhGxvze
bZsqBA4Q2chnB0BuTAryylUx2s55wRVEDiw3UTniHD9CCOyJbFOGJ9GFx9p2ngVS
0x5rAoGAacqYwilbjiiWAtie1g5ZMmgiTAjysIdCAKyz3HLMKjDptAAUFPM8Vwh+
YLy6Ekq/+HfUHhC5TDfNWwJa4XGs76bhUva4zgpbUJV+5pkHNn024akyxk+BtVBa
k7cpeFap0Oo/bvsmC0gA4r3mqug1MuwjUPAfzCOSA+euqBz7EVc=
-----END RSA PRIVATE KEY-----

110
README.md Normal file
View File

@ -0,0 +1,110 @@
setting.py is in detective_book folder you can see the settings of this project
# ira-lex Project Readme
Welcome to the documentation for the **ira-lex** Django project! This document serves as a guide to understanding the project's structure, functionality, and how to get it up and running on your local machine.
## Table of Contents
- [Project Overview](#project-overview)
- [Features](#features)
- [Getting Started](#getting-started)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Configuration](#configuration)
- [Usage](#usage)
- [Contributing](#contributing)
- [License](#license)
## Project Overview
[Project Name] is a Django-based web application designed to [briefly describe the project's main purpose and features].
## Features
- admin panel and customer panel (this repo contains just customer repo)
## Getting Started
Follow these instructions to set up and run the project on your local machine.
### Prerequisites
- Python [version 3.10]
- [Database] (MongoDB, PostgreSQL, Redis)[you don't need setup database in you local system. the database is run from server]
- [python celery and another library in requirements.txt file]
### Installation
1. Clone this repository to your local machine:
```bash
git clone [git@gitlab.com:yo3ef.amini/iralex-backend.git]
cd [iralex-backend]
```
2. Create a virtual environment:
```bash
virtualenv venv -p python3.10
```
3. Activate the virtual environment:
- On Windows:
```bash
venv\Scripts\activate
```
- On macOS and Linux:
```bash
source venv/bin/activate
```
4. Install the required dependencies:
```bash
pip install -r requirements.txt
```
## Configuration
1. Copy the `.env.example` file to `.env`:
```bash
cp .env.example .env
```
2. Edit the `.env` file and set the necessary environment variables:
- `SECRET_KEY`: Django secret key for security
- `DEBUG`: Set to `True` for development, `False` for production
- `DATABASE_URL`: URL to your database
- [Other configuration variables]
## Usage
1. Apply database migrations:
```bash
python manage.py migrate
```
2. Create a superuser account:
```bash
python manage.py createsuperuser
```
3. Start the development server:
```bash
python manage.py runserver
```
4. Access the application in your web browser at `http://127.0.0.1:8000/`.
Thank you for your interest in the [ira-lex] project. If you have any questions or need further assistance, please don't hesitate to [https://gitlab.com/ehsangheychisaz]. Happy coding!

31
account/Authentication.py Normal file
View File

@ -0,0 +1,31 @@
from django.core.handlers.wsgi import WSGIRequest
from account.TokenI import TokenI
from core.utility.Response import Response
class Authentication:
@staticmethod
def Authenticate():
def MethodWrapper(ViewMethod):
def ArgumentsWrapper(*args, **kwargs):
request = None
for arg in args:
if isinstance(arg, WSGIRequest):
request = arg
try:
if hasattr(request, 'lawyerUser'):
return ViewMethod(*args, **kwargs)
elif request.method == "OPTIONS":
return Response("Unauthorized")
else:
return Response("Unauthorized").Unauthorized()
except TokenI.TokenNotFoundException:
return Response("Unauthorized").Unauthorized()
except Exception as e:
print(e)
raise e
return ArgumentsWrapper
return MethodWrapper

154
account/LawyerUserI.py Normal file
View File

@ -0,0 +1,154 @@
from hashlib import sha256
from django.core.exceptions import ObjectDoesNotExist
from django.core.handlers.wsgi import WSGIRequest
from account.models import LawyerUser
from django.db.models import Q
from core.file_manager.models import FileInfo
from core.utility.Response import Response
class LawyerUserI:
lawyerUser: LawyerUser = None
def __init__(self, request: WSGIRequest = None, canCreate=False, canUpdate=False, *args, **kwargs):
if hasattr(request, "lawyerUser"):
print(request.lawyerUser)
self.lawyerUser = request.lawyerUser
for arg in args:
if isinstance(arg, LawyerUser):
self.lawyerUser = arg
_id = kwargs["id"] if "id" in kwargs else None
email_address = kwargs["email_address"] if "email_address" in kwargs else request.Input(
"email_address") if request is not None else None
first_name = kwargs["first_name"] if "first_name" in kwargs else request.Input(
"first_name") if request is not None else None
last_name = kwargs["last_name"] if "last_name" in kwargs else request.Input(
"last_name") if request is not None else None
phone_number = kwargs["phone_number"] if "phone_number" in kwargs else request.Input(
"phone_number") if request is not None else None
is_main = kwargs["is_main"] if "is_main" in kwargs else None
main = kwargs["main"] if "main" in kwargs else None
if not None and not isinstance(main, LawyerUser):
main = LawyerUser.objects.filter(pk=main).first()
# password = sha256(kwargs["password"].encode("utf-8")).hexdigest() if "password" in kwargs else None
avatar_id = kwargs["avatar_id"] if "avatar_id" in kwargs else request.Input(
"avatar_id") if request is not None else None
role_id = kwargs["role_id"] if "role_id" in kwargs else request.Input("role_id") if request is not None else None
fillParams = {
"email_address": email_address,
"password": None,
"first_name": first_name,
"last_name": last_name,
"phone_number": phone_number,
"is_main": is_main,
"main": main,
"avatar_id": avatar_id,
"role_id":role_id
}
if self.lawyerUser is None:
if _id is None:
self.lawyerUser = LawyerUser.objects.filter(Q(email_address=email_address)).first()
elif email_address is None:
self.lawyerUser = LawyerUser.objects.filter(Q(pk=_id)).first()
else:
self.lawyerUser = LawyerUser.objects.filter(Q(pk=_id) and Q(email_address=email_address)).first()
isCreated = False
if canCreate and (request is None or request.method == "POST"):
if self.lawyerUser is None and first_name is not None and last_name is not None and email_address is not None:
self.lawyerUser = LawyerUser.objects.create(**fillParams)
isCreated = True
try:
if canUpdate and not isCreated and (request is None or request.method == "PUT"):
if self.lawyerUser is not None and self.lawyerUser.password is not None:
for k in fillParams.keys():
if fillParams[k] is not None or k == 'avatar_id':
self.lawyerUser.__setattr__(k, fillParams[k])
self.lawyerUser.save()
except Exception as e:
raise e
if canUpdate and request is None or (request is not None and request.method == "POST" and isCreated) or (
request is not None and request.method == "PATH" and not isCreated):
if fillParams["avatar_id"] is not None:
fileInfo = FileInfo.objects.get(pk=fillParams["avatar_id"])
if fileInfo is not None:
if fileInfo.maintainer.id == self.lawyerUser.id:
fileInfo.section = FileInfo.Section.AVATAR
fileInfo.save()
self.lawyerUser.save()
@staticmethod
def LoadFromRequest(request):
lawyerUserI = LawyerUserI()
lawyerUserI.lawyerUser = request.lawyerUser
lawyerUserI.request = request
@staticmethod
def LoadById(_id):
try:
lawyerUserI = LawyerUserI()
lawyerUserI.lawyerUser = LawyerUser.objects.get(pk=_id)
return lawyerUserI
except ObjectDoesNotExist:
return None
@staticmethod
def LoadByIdIfUserCanFindThat(_lawyerUser, _id):
lawyerUserI = None
findWantLawyerUserI = LawyerUserI.LoadById(_id)
if isinstance(_lawyerUser, LawyerUser):
lawyerUserI = LawyerUserI.LoadById(_lawyerUser.id)
elif isinstance(_lawyerUser, LawyerUserI):
lawyerUserI = _lawyerUser
elif isinstance(_lawyerUser, int):
lawyerUserI = LawyerUserI.LoadById(_lawyerUser)
if lawyerUserI.lawyerUser.GetMain().id == findWantLawyerUserI.lawyerUser.GetMain().id:
return findWantLawyerUserI
raise LawyerUserI.NotAllowedException
def SetPassword(self, password):
self.lawyerUser.password = sha256(password.encode("utf-8")).hexdigest()
self.lawyerUser.save()
return self
def AddUser(self, email_address, first_name, last_name, phone_number, inviter_name='', role_id=''):
from core.verifier.VerifierI import VerifierI
from core.verifier.models import PendingVerify
if LawyerUser.objects.filter(email_address=email_address).first() is not None:
raise LawyerUserI.ConflictException
verifier = VerifierI(emailAddress=email_address)
verifier.CreatePending(PendingVerify.VerifyType.REGISTER, payload={
"email_address": email_address,
"first_name": first_name,
"last_name": last_name,
"phone_number": phone_number,
"is_main": False,
"role_id": role_id,
"main": self.lawyerUser.GetMain().id
}).SendMail(inviter_name=inviter_name, invited_name=first_name + ' ' + last_name, invited_user=True)
class ConflictException(Exception):
pass
class NotAllowedException(Exception):
pass
def chek_contract_validate(self):
pass

62
account/TokenI.py Normal file
View File

@ -0,0 +1,62 @@
import random
import string
from hashlib import sha256
from django.core.exceptions import ObjectDoesNotExist
from django.utils import timezone
from .LawyerUserI import LawyerUserI
from .models import Token
class TokenI:
class TokenSection:
AUTHENTICATION = "lua" # LawyerUser Authentication
token: Token = None
def __init__(self, section: str, _id: int = None, _token: str = None, emailAddress: str = None,
password: str = None):
if _id is not None:
try:
self.token = Token.objects.get(pk=_id)
except ObjectDoesNotExist:
raise TokenI.TokenNotFoundException
elif _token is not None:
try:
self.token = Token.objects.get(token=_token)
except ObjectDoesNotExist:
raise TokenI.TokenNotFoundException
elif emailAddress is not None:
lawyerUser = LawyerUserI(email_address=emailAddress)
if lawyerUser.lawyerUser is None:
raise TokenI.UserNotFoundException
else:
if lawyerUser.lawyerUser.is_removed == True:
raise TokenI.UserDeactivate
if lawyerUser.lawyerUser is not None and lawyerUser.lawyerUser.password == sha256(
password.encode("utf-8")).hexdigest():
_token = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(64))
_token = section + " " + _token
self.token = Token.objects.create(lawyer_user=lawyerUser.lawyerUser,
token=_token,
expire_date=timezone.now() + timezone.timedelta(days=30))
else:
raise TokenI.UserPassWrongException
def SetLawyerUser(self, lawyerUser):
self.token.lawyer_user = lawyerUser
self.token.save()
return self
class UserNotFoundException(Exception):
pass
class UserPassWrongException(Exception):
pass
class UserDeactivate(Exception):
pass
class TokenNotFoundException(Exception):
pass

0
account/__init__.py Normal file
View File

9
account/admin.py Normal file
View File

@ -0,0 +1,9 @@
from django.contrib import admin
from .models import *
from core.utility.DatabaseU import DatabaseU
DatabaseU.RegisterModelToAdmin(LawyerUser)
DatabaseU.RegisterModelToAdmin(Token)
DatabaseU.RegisterModelToAdmin(Group)

6
account/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class AccountConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'account'

View File

@ -0,0 +1,68 @@
# Generated by Django 4.0.2 on 2022-02-26 16:07
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='LawyerUser',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('email_address', models.CharField(max_length=64, unique=True)),
('password', models.CharField(blank=True, max_length=64, null=True)),
('avatar_url', models.CharField(blank=True, max_length=128, null=True)),
('first_name', models.CharField(max_length=64)),
('last_name', models.CharField(max_length=64)),
('phone_number', models.CharField(blank=True, max_length=64, null=True)),
('is_main', models.BooleanField(default=True)),
('total_uploaded_size', models.PositiveBigIntegerField(default=0)),
('is_verified', models.BooleanField(default=False)),
('is_removed', models.BooleanField(default=False)),
('permission', models.CharField(blank=True, choices=[('application_super_admin', 'Application Super Admin'), ('super_admin', 'Super Admin Permission'), ('admin', 'Admin Permission'), ('accounting', 'Accounting Permission'), ('user_a', 'User A Permission'), ('user_b', 'User B Permission')], default='super_admin', max_length=64, null=True)),
('is_application_admin', models.BooleanField(default=False)),
('main', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='account.lawyeruser')),
],
),
migrations.CreateModel(
name='Token',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('token', models.CharField(max_length=128)),
('expire_date', models.DateField()),
('payload', models.CharField(blank=True, max_length=256, null=True)),
('lawyer_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='account.lawyeruser')),
],
),
migrations.CreateModel(
name='Group',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('title', models.CharField(max_length=64)),
('main', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='group_main_user', to='account.lawyeruser')),
('users', models.ManyToManyField(to='account.LawyerUser')),
],
),
migrations.CreateModel(
name='FirebaseToken',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('web_client_token', models.CharField(blank=True, max_length=256, null=True)),
('phone_client_token', models.CharField(blank=True, max_length=256, null=True)),
('lawyer_user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='account.lawyeruser')),
],
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 4.0.2 on 2022-05-16 15:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('account', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='lawyeruser',
name='firm_avatar_url',
field=models.CharField(blank=True, max_length=256, null=True),
),
migrations.AlterField(
model_name='lawyeruser',
name='avatar_url',
field=models.CharField(blank=True, max_length=256, null=True),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 3.2.3 on 2022-09-01 10:33
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('account', '0002_lawyeruser_firm_avatar_url_and_more'),
]
operations = [
migrations.RenameField(
model_name='firebasetoken',
old_name='phone_client_token',
new_name='android_client_token',
),
migrations.AddField(
model_name='firebasetoken',
name='ios_client_token',
field=models.CharField(blank=True, max_length=256, null=True),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 3.2.3 on 2022-09-03 23:14
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('account', '0004_auto_20220901_1033'),
]
operations = [
migrations.AlterField(
model_name='firebasetoken',
name='lawyer_user',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='fcm_token', to='account.lawyeruser'),
),
]

View File

@ -0,0 +1,24 @@
# Generated by Django 3.2.3 on 2022-09-06 21:44
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('file_manager', '0001_initial'),
('account', '0005_alter_firebasetoken_lawyer_user'),
]
operations = [
migrations.RemoveField(
model_name='lawyeruser',
name='avatar_url',
),
migrations.AddField(
model_name='lawyeruser',
name='avatar',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='file_manager.fileinfo'),
),
]

View File

@ -0,0 +1,39 @@
# Generated by Django 3.2.3 on 2022-09-15 18:56
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('account', '0006_auto_20220906_2144'),
]
operations = [
migrations.CreateModel(
name='Role',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=128)),
('count', models.IntegerField(default=0)),
('key', models.CharField(max_length=128)),
],
),
migrations.CreateModel(
name='Admin',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('first_name', models.CharField(max_length=128)),
('last_name', models.CharField(max_length=128)),
('full_name', models.CharField(blank=True, max_length=256, null=True)),
('email', models.CharField(max_length=64)),
('gender', models.SmallIntegerField(choices=[(1, 'male'), (2, 'female'), (3, 'unknown')])),
('is_active', models.BooleanField(default=True)),
('phone', models.CharField(blank=True, max_length=32, null=True)),
('address', models.CharField(blank=True, max_length=512, null=True)),
('password', models.CharField(max_length=512)),
('role', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='account.role')),
],
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 3.2.3 on 2022-09-15 21:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('account', '0007_admin_role'),
]
operations = [
migrations.AlterField(
model_name='admin',
name='email',
field=models.CharField(max_length=64, unique=True),
),
migrations.AlterField(
model_name='admin',
name='gender',
field=models.SmallIntegerField(choices=[(1, 'male'), (2, 'female'), (3, 'unknown')], default=3),
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 3.2.3 on 2022-12-17 20:24
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('account', '0008_auto_20220915_2121'),
]
operations = [
migrations.RemoveField(
model_name='lawyeruser',
name='permission',
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 3.2.3 on 2022-12-17 21:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('permission', '0002_delete_userrole'),
('account', '0009_remove_lawyeruser_permission'),
]
operations = [
migrations.AddField(
model_name='lawyeruser',
name='permissions',
field=models.ManyToManyField(to='permission.Role'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.3 on 2022-12-18 22:54
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('account', '0010_lawyeruser_permissions'),
]
operations = [
migrations.RenameField(
model_name='lawyeruser',
old_name='permissions',
new_name='roles',
),
]

View File

@ -0,0 +1,24 @@
# Generated by Django 3.2.3 on 2023-01-05 18:21
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('permission', '0006_rolepermission_type'),
('account', '0011_rename_permissions_lawyeruser_roles'),
]
operations = [
migrations.RemoveField(
model_name='lawyeruser',
name='roles',
),
migrations.AddField(
model_name='lawyeruser',
name='role',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='users', to='permission.role'),
),
]

View File

@ -0,0 +1,24 @@
# Generated by Django 3.2.3 on 2023-06-16 21:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('permission', '0009_auto_20230616_2115'),
('account', '0012_auto_20230105_1821'),
]
operations = [
migrations.AddField(
model_name='lawyeruser',
name='permissions',
field=models.ManyToManyField(related_name='user_permissions', to='permission.Permission'),
),
migrations.AddField(
model_name='lawyeruser',
name='permissions_deny',
field=models.ManyToManyField(related_name='user_permissions_deny', to='permission.Permission'),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 4.2.2 on 2024-02-22 13:10
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('account', '0013_auto_20230616_2115'),
]
operations = [
migrations.CreateModel(
name='SearchHistory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('search', models.TextField(null=True)),
('create_time', models.DateTimeField(auto_now=True)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='account.lawyeruser')),
],
),
]

View File

245
account/models.py Normal file
View File

@ -0,0 +1,245 @@
import string
import random
from django.utils import timezone
from django.db import models
from django.db.models import Q, Sum
from django.forms import model_to_dict
class LawyerUser(models.Model):
SEARCH = [
"first_name",
"last_name",
"email_address"
]
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
email_address = models.CharField(max_length=64, unique=True)
password = models.CharField(max_length=64, blank=True, null=True)
avatar = models.ForeignKey(
'file_manager.FileInfo', null=True, blank=True, on_delete=models.SET_NULL)
firm_avatar_url = models.CharField(max_length=256, blank=True, null=True)
first_name = models.CharField(max_length=64)
last_name = models.CharField(max_length=64)
phone_number = models.CharField(max_length=64, blank=True, null=True)
is_main = models.BooleanField(default=True)
main = models.ForeignKey(
"self", blank=True, null=True, on_delete=models.CASCADE)
role = models.ForeignKey('permission.Role', on_delete=models.SET_NULL,
null=True, blank=True, related_name='users')
permissions = models.ManyToManyField(
'permission.Permission', related_name="user_permissions")
permissions_deny = models.ManyToManyField(
'permission.Permission', related_name="user_permissions_deny")
# جمع مقدار آپلود شده (به بایت)
total_uploaded_size = models.PositiveBigIntegerField(default=0)
is_verified = models.BooleanField(default=False)
is_removed = models.BooleanField(default=False)
# آخرین فاکتور
# آیا ادمین سیستم است ؟
is_application_admin = models.BooleanField(default=False)
def GetMain(self):
return self if self.is_main else self.main
@staticmethod
def Update(request, _id):
data = request.bodyDict
user = LawyerUser.GetReadableUsers(request.lawyerUser).get(pk=_id)
for key in data.keys():
setattr(user, key, data[key])
user.save()
return data
@staticmethod
def Delete(request, _id):
try:
user = LawyerUser.GetReadableUsers(request.lawyerUser).get(pk=_id)
user.is_removed = True
user.save()
return True
except Exception as e:
return str(e)
def TotalFirmUploadedSize(self):
return LawyerUser.objects.filter(Q(id=self.GetMain().id) |
Q(main__id=self.GetMain().id)).aggregate(Sum("total_uploaded_size"))[
"total_uploaded_size__sum"]
@staticmethod
def UpdateOrCreate(**kwargs):
lawyerUser, isCreated = LawyerUser.objects.update_or_create(email_address=kwargs["email_address"],
defaults=kwargs)
return lawyerUser
@staticmethod
def GetReadableUsers(lawyerUser):
return LawyerUser.objects.filter(Q(main__id=lawyerUser.GetMain().id) | Q(pk=lawyerUser.GetMain().id))
def ToDict(self, showPhoneNumber=False, showMainLawyerUserPhoneNumber=False, showSubscription=True):
try:
subscription = self.subscription
except Exception:
subscription = None
return {
"id": self.id,
"created_at": self.created_at,
"updated_at": self.updated_at,
"email_address": self.email_address,
"first_name": self.first_name,
"last_name": self.last_name,
"is_main": self.is_main,
# "phone_number": self.phone_number if showPhoneNumber else "hidden",
"phone_number": self.phone_number,
"roles": {'id': self.role.id, 'title': self.role.title} if self.role else {},
"avatar_url": self.avatar.GetUrl() if self.avatar else '',
"firm_avatar_url": self.GetMain().firm_avatar_url,
"main": self.main.ToDict(showPhoneNumber=showMainLawyerUserPhoneNumber) if self.main is not None else None,
"subscription": subscription.ToDict() if showSubscription and subscription is not None else None if subscription is None else "hidden",
"total_uploaded_size": self.total_uploaded_size,
"total_firm_uploaded_size": self.TotalFirmUploadedSize(),
}
def __str__(self):
return f"{self.first_name} {self.last_name}"
class NotOwnException(Exception):
pass
class Token(models.Model):
class Section:
AUTHENTICATION = "lua" # LawyerUser Authentication
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
token = models.CharField(max_length=128)
lawyer_user = models.ForeignKey(
LawyerUser, on_delete=models.CASCADE, blank=True, null=True)
expire_date = models.DateField()
payload = models.CharField(max_length=256, blank=True, null=True)
def ToDict(self):
_dict = model_to_dict(self)
_dict["lawyer_user"] = self.lawyer_user.ToDict(showPhoneNumber=True)
return _dict
@staticmethod
def CreateAuthenticationToken(lawyerUser):
_token = ''.join(random.choice(string.ascii_letters +
string.digits) for _ in range(64))
_token = Token.Section.AUTHENTICATION + " " + _token
token = Token.objects.create(lawyer_user=lawyerUser, token=_token,
expire_date=timezone.now() + timezone.timedelta(days=30))
return token
class Group(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
title = models.CharField(max_length=64)
main = models.ForeignKey(
LawyerUser, related_name="group_main_user", on_delete=models.CASCADE)
users = models.ManyToManyField(LawyerUser)
def ToDict(self):
modelDict = model_to_dict(self)
_users = []
usersAll = self.users.all()
for u in usersAll:
_users.append(u.ToDict())
modelDict["users"] = _users
return modelDict
class FirebaseToken(models.Model):
lawyer_user = models.OneToOneField(
LawyerUser, on_delete=models.CASCADE, related_name='fcm_token')
web_client_token = models.CharField(max_length=256, null=True, blank=True)
ios_client_token = models.CharField(max_length=256, null=True, blank=True)
android_client_token = models.CharField(
max_length=256, null=True, blank=True)
@staticmethod
def GetValidatedDataFromRequest(request):
# noinspection PyDictCreation
data = {}
data = request.bodyDict
data["lawyer_user"] = request.lawyerUser
return data
@staticmethod
def Create(request):
data = FirebaseToken.GetValidatedDataFromRequest(request)
firebaseToken = FirebaseToken.objects.create(**data)
return firebaseToken
@staticmethod
def Update(request, _id):
firebaseAccount = FirebaseToken.objects.get(pk=_id)
data = FirebaseToken.GetValidatedDataFromRequest(request)
for key in data.keys():
setattr(firebaseAccount, key, data[key])
firebaseAccount.save()
return firebaseAccount
def ToDict(self):
modelDict = model_to_dict(self)
return modelDict
class Role(models.Model):
title = models.CharField(max_length=128)
count = models.IntegerField(default=0)
key = models.CharField(max_length=128)
class Admin(models.Model):
first_name = models.CharField(max_length=128)
last_name = models.CharField(max_length=128)
full_name = models.CharField(max_length=256, null=True, blank=True)
email = models.CharField(max_length=64, unique=True)
role = models.ForeignKey(
Role, null=True, blank=True, on_delete=models.CASCADE)
gender = models.SmallIntegerField(choices=[
(1, 'male'),
(2, 'female'),
(3, 'unknown'),
], default=3)
is_active = models.BooleanField(default=True)
phone = models.CharField(max_length=32, null=True, blank=True)
address = models.CharField(max_length=512, null=True, blank=True)
password = models.CharField(max_length=512)
from django.utils import timezone
# Create your models here.
class SearchHistory(models.Model):
search = models.TextField(null=True)
create_time = models.DateTimeField(auto_now=True)
user = models.ForeignKey(LawyerUser , on_delete=models.PROTECT)
def Meta(self):
ordering = ['-create_time']
def save(self, *args, **kwargs):
# Check if the user already has ten or more text entries
if SearchHistory.objects.filter(user=self.user).count() >= 10:
removeSearch = SearchHistory.objects.filter(user=self.user).first()
removeSearch.delete()
super().save(*args, **kwargs)
def __str__(self):
return f"{self.user.first_name} {self.user.last_name} - {self.search}"

0
account/serializers.py Normal file
View File

0
account/tasks.py Normal file
View File

3
account/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

52
account/urls.py Normal file
View File

@ -0,0 +1,52 @@
import json
from django.urls import path
from permission.views import getAllPermission, getUserPermission
from subscription.subscription import Subscription
from messenger.Messenger import Messenger
from .views import *
def test(request):
Subscription.get_active_contract(request.lawyerUser)
return True
with open("ex.txt", "a") as res:
if request.method == 'POST':
var = request.POST
if request.method == 'GET':
var = request.GET
res.write("\n")
res.write("test")
res.write(json.dumps(var))
# Messenger.SendMail(toEmails=['yo3ef.amini@gmail.com'], message="one conected", subject='test')
return Response(200)
urlpatterns = [
path("", Account),
path("register/", Register),
path("forgot/", ForgotPassword),
path("change-password/", ChangePassword),
path("change-email/", ChangeEmailAddress),
path("verify/", Verify),
path("token/", GenerateToken),
path("add/", AddUser),
path("edit/<int:_id>", EditFirmUser),
path("delete/<int:_id>", DeleteFirmUser),
path("permit/<int:userId>/", PermitPermission),
path("list/", GetListOfFirmUser),
path("edit/", GetListOfFirmUser),
path("group/", GroupView),
path("group/<int:groupId>/", SetGroupUsers),
path("group/<int:groupId>/edit/", SetGroupUsers),
path("group/<int:groupId>/delete/", DeleteGroup),
path("firebase/token/", AssignLawyerUserFirebaseToken),
path("google/login/", LoginWithGoogle),
path("facebook/login/" , LoginWithFacebook),
path("google/oauth2/", GoogleOAuth2),
path("firm/avatar/", FirmAvatar),
path("payment/", test),
path("permissions", getAllPermission),
path("my-permission", getUserPermission),
]

433
account/views.py Normal file
View File

@ -0,0 +1,433 @@
import os
from hashlib import sha256
from PIL import Image
from django.utils import timezone
from django.db.models import Q
from google.auth.transport import requests
from google.oauth2 import id_token
from messenger.Messenger import Messenger
from account.Authentication import Authentication
from account.LawyerUserI import LawyerUserI
from account.TokenI import TokenI
from account.models import LawyerUser, Group, FirebaseToken, Token
from contact.models import Contact
from core.file_manager.models import FileInfo
from core.utility.Response import Response
from core.verifier.VerifierI import VerifierI
from core.verifier.models import PendingVerify
from detective_book.settings import ROOT_DIR
from core.utility.Response import Response
from subscription.models import Contract
from subscription.subscription import Subscription
from django.http import JsonResponse
from django.http import Http404 , HttpResponse
from datetime import datetime, time, timedelta
import pytz
@Authentication.Authenticate()
def Account(request):
# if request.method == "GET" :
return Response(LawyerUserI(id=request.lawyerUser.id, request=request, canUpdate=True).lawyerUser.ToDict(True))
# else:
# return Response.NotAllowed()
def Register(request):
# if request.method == "POST":
email = request.Input("email_address")
print(email)
if email == None or email == "":
return Response({"status": False}).NotAcceptable()
if LawyerUser.objects.filter(email_address=email.lower()).exists() != True:
verifier = VerifierI(emailAddress=request.Input("email_address"))
verifier.CreatePending(PendingVerify.VerifyType.REGISTER, payload={
"email_address": request.Input("email_address"),
"first_name": request.Input("first_name"),
"last_name": request.Input("last_name"),
"phone_number": request.Input("phone_number"),
"is_main": True,
# "permission": LawyerUser.Permission.SUPER_ADMIN_PERMISSION
})
verifier.SendMail(name=request.Input("first_name", "") + " " + request.Input("last_name", ""))
# verifier.SendNewmail(name=request.Input("first_name", "") + " " + request.Input("last_name", ""),
# phone=request.Input("phone_number"))
return Response({"status": True})
else:
return Response({"status": False, "message": "Email address is exists"}).Conflict()
def ForgotPassword(request):
if request.method == "POST":
if len(request.Input("email_address")) == 0:
return Response("bad request").NotAllowed()
lawyerUser = LawyerUser.objects.filter(
email_address=request.Input("email_address")).first()
if lawyerUser is None:
return Response("User not found").NotFound()
userLastForget = PendingVerify.objects.filter(email_address=request.Input("email_address")).order_by("-created_at").first()
if userLastForget:
lasttime = userLastForget.created_at
time = datetime.now()
print((time - lasttime).seconds)
if (time-lasttime).seconds > 180 :
verifier = VerifierI(emailAddress=request.Input("email_address")).CreatePending(
PendingVerify.VerifyType.FORGOT_PASSWORD, payload=None)
verifier.SendMail(name=f'{lawyerUser.first_name} {lawyerUser.last_name}')
return Response({"status": True})
else:
return Response(f"you are in time limit for {180 - (time-lasttime).seconds}").NotAllowed()
else:
verifier = VerifierI(emailAddress=request.Input("email_address")).CreatePending(
PendingVerify.VerifyType.FORGOT_PASSWORD, payload=None)
verifier.SendMail(name=f'{lawyerUser.first_name} {lawyerUser.last_name}')
return Response({"status": True})
if request.method == "OPTIONS":
return Response("not allowed").NotAllowed()
# if request.method == "POST":
# if request.Input("email_address")== "":
# return Response("email field is empty").NotFound()
# else:
# lawyerUser = LawyerUser.objects.filter(
# email_address=request.Input("email_address")).first()
# if lawyerUser is None:
# return Response("User not found").NotFound()
# verifier = VerifierI(emailAddress=request.Input("email_address"))
# timeClient = PendingVerify.objects.filter(email_address=request.Input("email_address")).first().created_at
# timeRequest = datetime.now()
# if (timeRequest - timeClient).seconds >= 180:
# verifier.CreatePending(
# PendingVerify.VerifyType.FORGOT_PASSWORD, payload=None)
# verifier.SendMail()
# return Response({"status": True}).Correct()
# else :
# return Response(f"you are in time limit and you should wait for {180 - (timeRequest - timeClient).seconds} seconds").NotAcceptable()
# else:
# Response.NotAllowed()
@Authentication.Authenticate()
def AddUser(request):
try:
if not Subscription.chek_user_limit(request.lawyerUser):
return JsonResponse(data={
"message": "You have reached the limit of adding users. "
}, status=422)
LawyerUserI(request).AddUser(email_address=request.Input("email_address"),
first_name=request.Input("first_name"),
last_name=request.Input("last_name"),
phone_number=request.Input(
"phone_number"),
role_id=request.Input("role_id"),
# permission=LawyerUser.Permission.USER_B_PERMISSION, TODO Add Permission
inviter_name=request.lawyerUser.first_name + ' ' + request.lawyerUser.last_name)
return Response({"status": True})
except LawyerUserI.ConflictException:
return Response("Email address exists.").Conflict()
def Verify(request):
try:
lawyerUser = None
verifier = VerifierI(code=request.Input("code"))
payload = verifier.pendingVerify.payload
if verifier.pendingVerify.verify_type == PendingVerify.VerifyType.REGISTER:
if 'main' in payload:
main = LawyerUser.objects.get(pk=payload['main'])
main_contract = Subscription.get_active_contract(main)
if not main_contract:
raise "You`re inviter plan has been expired."
can_add_user = Subscription.chek_user_limit(main)
if not can_add_user:
raise "You`re inviter can`t add any user more."
main_contract.user_usage += 1
main_contract.save()
lawyerUser = LawyerUserI(**payload, canCreate=True)
lawyerUser.lawyerUser.contracts.add(main_contract)
lawyerUser.SetPassword(request.Input("password"))
else:
lawyerUser = LawyerUserI(**payload, canCreate=True)
_now = timezone.now()
new_trial = Contract.objects.create(
status=2,
from_date=_now,
to_date=_now + timezone.timedelta(days=14),
owner_id=lawyerUser.lawyerUser.id,
user_limit=9999,
allowed_delay_days=0,
discounted_price=0,
total_price=0,
payed_amount=0,
installments_count=1,
payable_amount=0,
storage_limit=1000000,
type=3,
)
new_trial.save()
lawyerUser.lawyerUser.contracts.add(new_trial)
lawyerUser.SetPassword(request.Input("password"))
print(lawyerUser.lawyerUser.first_name ,lawyerUser.lawyerUser.last_name,lawyerUser.lawyerUser.phone_number)
verifier.SendNewmail(name=lawyerUser.lawyerUser.first_name+lawyerUser.lawyerUser.last_name,
phone=lawyerUser.lawyerUser.phone_number)
elif verifier.pendingVerify.verify_type == PendingVerify.VerifyType.FORGOT_PASSWORD:
lawyerUser = LawyerUserI.LoadById(
LawyerUser.objects.get(email_address=verifier.pendingVerify.email_address).id)
lawyerUser.SetPassword(request.Input("password"))
elif verifier.pendingVerify.verify_type == PendingVerify.VerifyType.CHANGE_EMAIL_ADDRESS:
lawyerUser = LawyerUserI.LoadById(
LawyerUser.objects.get(email_address=verifier.pendingVerify.payload["old_email_address"]).id)
lawyerUser.lawyerUser.email_address = verifier.pendingVerify.payload["email_address"]
lawyerUser.lawyerUser.save()
verifier.DeleteSimilar()
return Response(lawyerUser.lawyerUser)
except VerifierI.CodeNotFoundException:
return Response({"message": "Code not found"}).NotFound()
@Authentication.Authenticate()
def ChangePassword(request):
if request.lawyerUser.password == sha256(request.bodyDict["old_password"].encode("utf-8")).hexdigest():
request.lawyerUser.password = sha256(
request.bodyDict["new_password"].encode("utf-8")).hexdigest()
request.lawyerUser.save()
return Response(request.lawyerUser)
else:
return Response({"message": "Old password is incorrect"}).NotAcceptable()
@Authentication.Authenticate()
def ChangeEmailAddress(request):
verifier = VerifierI(emailAddress=request.Input("email_address"))
verifier.CreatePending(PendingVerify.VerifyType.CHANGE_EMAIL_ADDRESS, payload={
"old_email_address": request.lawyerUser.email_address,
"email_address": request.Input("email_address")
})
verifier.SendMail(request.lawyerUser.first_name +
" " + request.lawyerUser.last_name)
return Response({"status": True})
def GenerateToken(request):
try:
token = TokenI(section=TokenI.TokenSection.AUTHENTICATION, emailAddress=request.Input("email_address"),
password=request.Input("password"))
return Response(token.token)
except TokenI.UserNotFoundException:
return Response({"message": "Cannot find the user with this email"}).NotFound()
except TokenI.UserPassWrongException:
return Response({"message": "Cannot find the user with this pass"}).NotFound()
@Authentication.Authenticate()
def PermitPermission(request, userId):
if request.method == "PUT":
try:
lawyerUserI = LawyerUserI.LoadByIdIfUserCanFindThat(
request.lawyerUser, userId)
lawyerUserI.lawyerUser.permission = request.Input("permission")
lawyerUserI.lawyerUser.save()
return Response(content=lawyerUserI.lawyerUser)
except LawyerUserI.NotAllowedException:
return Response("Not found-ER8529422344").NotFound()
else:
return Response("Nothing").NotAllowed()
@Authentication.Authenticate()
def GetListOfFirmUser(request):
return Response(
LawyerUser.objects.filter(Q(pk=request.lawyerUser.GetMain().id) | Q(main_id=request.lawyerUser.GetMain().id), is_removed=False).order_by('-created_at'))
@Authentication.Authenticate()
def EditFirmUser(request, _id):
return Response(LawyerUser.Update(request=request, _id=_id))
@Authentication.Authenticate()
def DeleteFirmUser(request, _id):
return Response(LawyerUser.Delete(request, _id=_id))
@Authentication.Authenticate()
# @Permission.Require(LawyerUser.Permission.ACCOUNTING_PERMISSION)
def GroupView(request):
if request.method == "GET":
list_of_group = Group.objects.filter(main_id=request.lawyerUser.GetMain().id).all().order_by('-created_at')
# print(list_of_group)
return Response(list_of_group)
elif request.method == "POST":
group = Group.objects.create(title=request.Input(
"title"), main=request.lawyerUser.GetMain())
if request.Input("users"):
for u in request.Input("users"):
lawyerUser = LawyerUserI.LoadByIdIfUserCanFindThat(
request.lawyerUser.id, u)
group.users.add(lawyerUser.lawyerUser)
return Response(group)
@Authentication.Authenticate()
def SetGroupUsers(request, groupId):
if request.method == "GET":
group = Group.objects.get(
main_id=request.lawyerUser.GetMain().id, pk=groupId)
return Response(group)
if request.method == "PUT":
group = Group.objects.get(
main_id=request.lawyerUser.GetMain().id, pk=groupId)
group.title = request.Input("title")
group.save()
group.users.clear()
print(request.Input("users"))
for u in request.Input("users"):
lawyerUser = LawyerUserI.LoadByIdIfUserCanFindThat(
request.lawyerUser.id, u)
group.users.add(lawyerUser.lawyerUser)
return Response(group)
@Authentication.Authenticate()
def DeleteGroup(request, groupId):
group = Group.objects.get(
main_id=request.lawyerUser.GetMain().id, pk=groupId)
group.delete()
return Response({"status": "true"})
# def LoginWithGoogle(request):
# clientId = "222474890494-jo5uf8i4tnuggnicdo475fdfk46an9oq.apps.googleusercontent.com"
# clientSecret = "psmJdLCoIhqveLqV-scCSb8C"
# redirectUri = "https://ira-lex.com/login-by-google/"
#
# authorizationBaseUrl = "https://accounts.google.com/o/oauth2/v2/auth"
# tokenUrl = "https://www.googleapis.com/oauth2/v4/toke"
#
# scope = ["https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile"]
#
@Authentication.Authenticate()
def AssignLawyerUserFirebaseToken(request):
token = FirebaseToken.objects.filter(
lawyer_user__id=request.lawyerUser.id).first()
if token is None:
token = FirebaseToken.Create(request)
else:
token.Update(request, token.id)
return Response(token)
def LoginWithGoogle(request):
loginPageHtmlPath = os.path.join(
ROOT_DIR, "assets/google-oauth2/index.html")
with open(loginPageHtmlPath, "r") as file:
loginPageHtml = file.read()
return Response(loginPageHtml)
def LoginWithFacebook(request):
loginPageHtmlPath = os.path.join(
ROOT_DIR, "assets/facebook-login/index.html")
with open(loginPageHtmlPath, "r") as file:
loginPageHtml = file.read()
return Response(loginPageHtml)
def GoogleOAuth2(request):
WEB_CLIENT_ID = "986858475219-461v2efu5b1ghfsofnajak56pt806spa.apps.googleusercontent.com"
ANDROID_CLIENT_ID = "986858475219-51t72fthf2p6p79rjgg47e6se5oalvf7.apps.googleusercontent.com"
try:
idInfo = id_token.verify_oauth2_token(
request.bodyDict["id_token"], requests.Request())
if idInfo["aud"] not in [WEB_CLIENT_ID, ANDROID_CLIENT_ID,
"986858475219-1n02hgjcbuc5e9onjb2hv558rie9mnlo.apps.googleusercontent.com",
"986858475219-1n02hgjcbuc5e9onjb2hv558rie9mnlo.apps.googleusercontent.com"]:
raise ValueError("Could not verify audience")
lawyerUserParams = {
"email_address": idInfo["email"],
"first_name": idInfo["given_name"],
"last_name": idInfo["family_name"],
"avatar_url": idInfo["picture"],
"is_verified": True
}
lawyerUser = LawyerUser.UpdateOrCreate(**lawyerUserParams)
return Response(Token.CreateAuthenticationToken(lawyerUser))
except Exception as e:
return Response(str(e)).Forbidden()
@Authentication.Authenticate()
def FirmAvatar(request):
oldFileInfo = None
if request.lawyerUser.GetMain().firm_avatar_url is not None:
oldFileInfo = FileInfo.GetByFileName(
request.lawyerUser.GetMain().firm_avatar_url.split("/")[-1], True)
if "file" in request.FILES:
try:
fileInfo = FileInfo.CreateByRequest(request, True, 3 * 1024 * 1024)
except FileInfo.TooLargeException:
return Response().TooLarge()
try:
Image.open(fileInfo.path).verify()
except Exception:
os.remove(fileInfo.path)
fileInfo.delete()
return Response().Forbidden()
request.lawyerUser.GetMain().firm_avatar_url = fileInfo.GetUrl()
request.lawyerUser.GetMain().save()
else:
request.lawyerUser.GetMain().firm_avatar_url = None
request.lawyerUser.GetMain().save()
if oldFileInfo is not None:
try:
if os.path.exists(oldFileInfo.path):
os.remove(oldFileInfo.path)
oldFileInfo.delete()
except Exception:
pass
return Response(request.lawyerUser.GetMain())
def get_fullname(user, contact=False):
if not contact and isinstance(user, LawyerUser):
if not user:
return ''
return user.first_name + ' ' + user.last_name
elif isinstance(user, Contact):
person = user.person_set.first()
company = user.company_set.first()
return (person.first_name + ' ' + person.last_name) if person else company.name
return '-'

0
activity/__init__.py Normal file
View File

3
activity/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
activity/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class ActivityConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'activity'

View File

@ -0,0 +1,80 @@
# Generated by Django 4.0.2 on 2022-02-26 16:07
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('account', '0001_initial'),
('contact', '0001_initial'),
('matter', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='ExpenseCategory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=32)),
('rate', models.FloatField(default=0)),
('expense_type', models.IntegerField(choices=[(1, 'Disbursement'), (2, 'Recoveries')])),
('is_removed', models.BooleanField(default=False)),
('creator', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='account.lawyeruser')),
],
),
migrations.CreateModel(
name='TimeEntryCategory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=32)),
('rate', models.FloatField(default=0)),
('is_removed', models.BooleanField(default=False)),
('creator', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='account.lawyeruser')),
],
),
migrations.CreateModel(
name='TimeEntry',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('duration', models.FloatField(default=0)),
('date', models.DateField(blank=True, null=True)),
('rate', models.FloatField(default=0)),
('description', models.TextField(default='')),
('is_no_billable', models.BooleanField(default=False)),
('is_removed', models.BooleanField(default=False)),
('is_used_in_invoice', models.BooleanField(default=False)),
('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='activity.timeentrycategory')),
('creator', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='time_entry_creator_set', to='account.lawyeruser')),
('matter', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='matter.matter')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='time_entry_user_set', to='account.lawyeruser')),
],
),
migrations.CreateModel(
name='ExpenseEntry',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('date', models.DateField(blank=True, null=True)),
('is_used_in_invoice', models.BooleanField(default=False)),
('expense_type', models.IntegerField(choices=[(1, 'Disbursement'), (2, 'Recoveries')])),
('reference', models.CharField(blank=True, max_length=32, null=True)),
('quantity', models.IntegerField(default=1)),
('amount', models.FloatField(default=0)),
('rate', models.FloatField(default=0)),
('description', models.TextField(blank=True, null=True)),
('is_removed', models.BooleanField(default=False)),
('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='activity.expensecategory')),
('creator', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='expense_entry_creator_set', to='account.lawyeruser')),
('matter', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='matter.matter')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='expense_entry_user_set', to='account.lawyeruser')),
('vendor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='contact.contact')),
],
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 3.2.3 on 2022-12-07 20:12
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('task', '0002_alter_tasklist_practice_area'),
('activity', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='timeentry',
name='task',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='task.task'),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 4.2.2 on 2025-01-02 08:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('activity', '0002_timeentry_task'),
]
operations = [
migrations.AddField(
model_name='expenseentry',
name='is_tax',
field=models.BooleanField(default=False, null=True),
),
migrations.AddField(
model_name='timeentry',
name='is_tax',
field=models.BooleanField(default=False, null=True),
),
]

View File

432
activity/models.py Normal file
View File

@ -0,0 +1,432 @@
import os
from asgiref.sync import async_to_sync
from celery import shared_task
from django.db import models
from django.db.models import Q
from django.forms import model_to_dict
from django.utils.dateparse import parse_date
from account.models import LawyerUser
# from account.views import get_fullname
from contact.models import Contact
from detective_book.settings import ROOT_DIR, BASE_URL
from matter.models import Matter
from messenger.Messenger import Messenger
from permission.check_permission import CheckUserNotification
from task.models import Task
from timeline.timeline import Timeline
# دسته بندی TimeEntry
class TimeEntryCategory(models.Model):
SEARCH = ["name"]
creator = models.ForeignKey(LawyerUser, on_delete=models.CASCADE)
name = models.CharField(max_length=32)
# نرخ پیشفرض این دسته
rate = models.FloatField(default=0)
is_removed = models.BooleanField(default=False)
def ToDict(self):
modelDict = model_to_dict(self)
modelDict["creator"] = self.creator.ToDict()
return modelDict
@staticmethod
def GetValidatedDataFromRequest(request):
data = request.bodyDict
data["creator"] = request.lawyerUser
return data
@staticmethod
def Create(request):
data = ExpenseCategory.GetValidatedDataFromRequest(request)
timeEntryCategory = TimeEntryCategory.objects.create(**data)
Timeline.InsertEvent(lawyerUser=request.lawyerUser,
row=timeEntryCategory,
action=Timeline.Action.CREATE,
message=None)
return timeEntryCategory
@staticmethod
def Update(request, _id):
data = TimeEntryCategory.GetValidatedDataFromRequest(request)
timeEntryCategory = TimeEntryCategory.List(request).get(pk=_id)
for key in data.keys():
setattr(timeEntryCategory, key, data[key])
timeEntryCategory.save()
Timeline.InsertEvent(lawyerUser=request.lawyerUser,
row=timeEntryCategory,
action=Timeline.Action.EDIT,
message=None)
return timeEntryCategory
@staticmethod
def Remove(request, _id):
timeEntryCategory = TimeEntryCategory.List(request).get(pk=_id)
timeEntryCategory.is_removed = True
timeEntryCategory.save()
Timeline.InsertEvent(lawyerUser=request.lawyerUser,
row=timeEntryCategory,
action=Timeline.Action.REMOVE,
message=None)
return timeEntryCategory
@staticmethod
def List(request, inIsRemoved=False):
return TimeEntryCategory.objects.filter(Q(creator__id=request.lawyerUser.GetMain().id) |
Q(creator__main__id=request.lawyerUser.GetMain().id)).filter(
is_removed=inIsRemoved).all()
class TimeEntry(models.Model):
SEARCH = [
"description",
"matter__title",
"user__first_name",
"user__last_name",
]
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
creator = models.ForeignKey(LawyerUser, on_delete=models.CASCADE, related_name="time_entry_creator_set")
# پرونده
matter = models.ForeignKey(Matter, blank=True, null=True, on_delete=models.CASCADE)
# مدت زمان به دقیقه
duration = models.FloatField(default=0)
date = models.DateField(blank=True, null=True)
user = models.ForeignKey(LawyerUser, on_delete=models.CASCADE, related_name="time_entry_user_set")
rate = models.FloatField(default=0)
category = models.ForeignKey(TimeEntryCategory, blank=True, null=True, on_delete=models.CASCADE)
description = models.TextField(default="")
task = models.ForeignKey(Task, null=True, blank=True, on_delete=models.SET_NULL)
# آیا در فاکتور میرود ؟
is_no_billable = models.BooleanField(default=False)
is_removed = models.BooleanField(default=False)
# اگر در فاکتور استفاده شده باشد True میشود. چون هم TimeEntry باید یک بار فاکتور شود
is_used_in_invoice = models.BooleanField(default=False)
is_tax = models.BooleanField(default=False , null=True)
discount_cash = models.BigIntegerField(null=True)
discount = models.IntegerField(null=True)
@staticmethod
def GetValidatedDataFromRequest(request):
data = request.bodyDict
data["creator"] = request.lawyerUser
if "matter" in data and data["matter"] is not None:
data["matter"] = Matter.GetReadableMatters(lawyerUser=request.lawyerUser).get(pk=data["matter"])
if "user" in data and data["user"] is not None:
data["user"] = LawyerUser.GetReadableUsers(request.lawyerUser).get(pk=data["user"])
if "category" in data and data["category"] is not None:
data["category"] = TimeEntryCategory.objects.get(pk=data["category"])
if "date" in data and data["date"] is not None:
data["date"] = parse_date(request.Input("date"))
return data
def ToDict(self):
modelDict = model_to_dict(self)
modelDict["creator"] = self.creator.ToDict()
if self.matter is not None:
modelDict["matter"] = self.matter.ToDict()
if self.user is not None:
modelDict["user"] = self.user.ToDict()
if self.category is not None:
modelDict["category"] = self.category.ToDict()
return modelDict
@staticmethod
def Create(request):
data = TimeEntry.GetValidatedDataFromRequest(request)
timeEntry = TimeEntry.objects.create(**data)
Timeline.InsertEvent(lawyerUser=request.lawyerUser,
row=timeEntry,
action=Timeline.Action.CREATE,
message=None)
if 'matter' in data and data['matter']:
matter = data['matter']
matter.usage_budget += int(float(timeEntry.rate) * float(timeEntry.duration))
matter.save()
if matter.has_notify and matter.usage_budget >= matter.budget * (matter.notify_limit / 100):
sendBudgetLimitWarning.delay(matter_id=matter.id)
return timeEntry
@staticmethod
def Update(request, _id):
data = TimeEntry.GetValidatedDataFromRequest(request)
timeEntry = TimeEntry.List(request).get(pk=_id)
if 'matter' in data and data['matter']:
matter = data['matter']
matter.usage_budget -= int(float(timeEntry.rate) * float(timeEntry.duration))
matter.save()
for key in data.keys():
setattr(timeEntry, key, data[key])
timeEntry.save()
Timeline.InsertEvent(lawyerUser=request.lawyerUser,
row=timeEntry,
action=Timeline.Action.EDIT,
message=None)
if 'matter' in data and data['matter']:
matter = data['matter']
matter.usage_budget += int(float(timeEntry.rate) * float(timeEntry.duration))
matter.save()
if matter.has_notify and matter.usage_budget >= matter.budget * (matter.notify_limit / 100):
sendBudgetLimitWarning.delay(matter_id=matter.id)
return timeEntry
@staticmethod
def Remove(request, _id):
timeEntry = TimeEntry.List(request).get(pk=_id)
timeEntry.is_removed = True
timeEntry.save()
Timeline.InsertEvent(lawyerUser=request.lawyerUser,
row=timeEntry,
action=Timeline.Action.REMOVE,
message=None)
return timeEntry
@staticmethod
def List(request, inIsRemoved=False):
matterIds = Matter.GetReadableMatters(request.lawyerUser).values_list("id", flat=True)
return TimeEntry.objects.filter(Q(matter__id__in=matterIds) | Q(creator__id=request.lawyerUser.id)).filter(
is_removed=inIsRemoved).all()
@staticmethod
def get_amount(entry):
return float("{:.2f}".format(entry.duration * entry.rate))
# دسته بندی Expense
class ExpenseCategory(models.Model):
SEARCH = ["name"]
class ExpenseType(models.IntegerChoices):
DISBURSEMENT = 1,
RECOVERIES = 2,
creator = models.ForeignKey(LawyerUser, on_delete=models.CASCADE)
name = models.CharField(max_length=32)
rate = models.FloatField(default=0)
expense_type = models.IntegerField(choices=ExpenseType.choices)
is_removed = models.BooleanField(default=False)
def ToDict(self):
modelDict = model_to_dict(self)
modelDict["creator"] = self.creator.ToDict()
modelDict["vendor"] = self.creator.ToDict()
return modelDict
@staticmethod
def GetValidatedDataFromRequest(request):
data = request.bodyDict
data["creator"] = request.lawyerUser
return data
@staticmethod
def Create(request):
print('hi')
data = ExpenseCategory.GetValidatedDataFromRequest(request)
expenseCategory = ExpenseCategory.objects.create(**data)
Timeline.InsertEvent(lawyerUser=request.lawyerUser,
row=expenseCategory,
action=Timeline.Action.CREATE,
message=None)
return expenseCategory
@staticmethod
def Update(request, _id):
data = ExpenseCategory.GetValidatedDataFromRequest(request)
expenseCategory = ExpenseCategory.List(request).get(pk=_id)
for key in data.keys():
setattr(expenseCategory, key, data[key])
expenseCategory.save()
Timeline.InsertEvent(lawyerUser=request.lawyerUser,
row=expenseCategory,
action=Timeline.Action.EDIT,
message=None)
return expenseCategory
@staticmethod
def Remove(request, _id):
expenseCategory = ExpenseCategory.List(request).get(pk=_id)
expenseCategory.is_removed = True
expenseCategory.save()
Timeline.InsertEvent(lawyerUser=request.lawyerUser,
row=expenseCategory,
action=Timeline.Action.REMOVE,
message=None)
return expenseCategory
@staticmethod
def List(request, inIsRemoved=False):
return ExpenseCategory.objects.filter(Q(creator__id=request.lawyerUser.GetMain().id) |
Q(creator__main__id=request.lawyerUser.GetMain().id)).filter(
is_removed=inIsRemoved).all()
class ExpenseEntry(models.Model):
SEARCH = ["matter__title"]
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
creator = models.ForeignKey(LawyerUser, on_delete=models.CASCADE, related_name="expense_entry_creator_set")
user = models.ForeignKey(LawyerUser, on_delete=models.CASCADE, related_name="expense_entry_user_set")
matter = models.ForeignKey(Matter, blank=True, null=True, on_delete=models.CASCADE)
date = models.DateField(blank=True, null=True)
# اگر در فاکتور استفاده شده باشد True میشود چون فقط یکبار باید در فاکتور استفاده شود
is_used_in_invoice = models.BooleanField(default=False)
is_tax = models.BooleanField(default=False , null=True)
class ExpenseType(models.IntegerChoices):
DISBURSEMENT = 1,
RECOVERIES = 2,
expense_type = models.IntegerField(choices=ExpenseType.choices)
category = models.ForeignKey(ExpenseCategory, blank=True, null=True, on_delete=models.CASCADE)
# دقیق نمیدونم ولی فکر میکنم مثلا میگه این هزینه برای چه چیز فیزیکی یا ... استفاده شده - آقای کراری بهتر میدونند
reference = models.CharField(max_length=32, blank=True, null=True)
# تعداد - مثلا ۱۰ تا جعبه خریده شده
quantity = models.IntegerField(default=1)
# تفاوت amount با rate رو نمیدونم. احتمالا آقای کراری از یکی استفاده کرده
amount = models.FloatField(default=0)
rate = models.FloatField(default=0)
# میشه به یک شخص هم نسبت پیدا کنه اما شاید بیشتر جنبه یاد‌آوری داره
vendor = models.ForeignKey(Contact, blank=True, null=True, on_delete=models.CASCADE)
description = models.TextField(blank=True, null=True)
is_removed = models.BooleanField(default=False)
discount_cash = models.BigIntegerField(null=True)
discount = models.IntegerField(null=True)
@staticmethod
def GetValidatedDataFromRequest(request):
data = request.bodyDict
if 'tax' in data:
data.pop('tax')
print(data)
data["creator"] = request.lawyerUser
if "matter" in data and data["matter"] is not None:
data["matter"] = Matter.GetReadableMatters(lawyerUser=request.lawyerUser).get(pk=data["matter"])
if "user" in data and data["user"] is not None:
data["user"] = LawyerUser.GetReadableUsers(request.lawyerUser).get(pk=data["user"])
if "date" in data and data["date"] is not None:
data["date"] = parse_date(request.Input("date"))
if "vendor" in data and data["vendor"] is not None:
data["vendor"] = Contact.GetAccessibleContacts(request.lawyerUser).get(pk=data["vendor"])
if "category" in data and data["category"] is not None:
data["category"] = ExpenseCategory.objects.get(pk=data["category"])
if data["category"].creator.GetMain().id != data["creator"].GetMain().id:
raise LawyerUser.NotOwnException
return data
def ToDict(self):
modelDict = model_to_dict(self)
modelDict["creator"] = self.creator.ToDict()
if self.matter is not None:
modelDict["matter"] = self.matter.ToDict()
if self.user is not None:
modelDict["user"] = self.user.ToDict()
if self.category is not None:
modelDict["category"] = self.category.ToDict()
if self.vendor is not None:
modelDict["vendor"] = self.vendor.ToDict()
return modelDict
@staticmethod
def Create(request):
data = ExpenseEntry.GetValidatedDataFromRequest(request)
print(data)
expenseEntry = ExpenseEntry.objects.create(**data)
Timeline.InsertEvent(lawyerUser=request.lawyerUser,
row=expenseEntry,
action=Timeline.Action.CREATE,
message=None)
if 'matter' in data and data['matter']:
matter = data['matter']
matter.usage_budget += float(data['amount'])
matter.save()
if matter.has_notify and matter.usage_budget >= matter.budget * (matter.notify_limit / 100):
sendBudgetLimitWarning.delay(matter_id=matter.id)
return expenseEntry
@staticmethod
def Update(request, _id):
data = ExpenseEntry.GetValidatedDataFromRequest(request)
expenseEntry = ExpenseEntry.List(request).get(pk=_id)
matter = data['matter']
if 'matter' in data and data['matter']:
matter.usage_budget -= expenseEntry.amount
matter.save()
for key in data.keys():
setattr(expenseEntry, key, data[key])
expenseEntry.save()
Timeline.InsertEvent(lawyerUser=request.lawyerUser,
row=expenseEntry,
action=Timeline.Action.EDIT,
message=None)
if 'matter' in data and data['matter']:
matter = data['matter']
matter.usage_budget += float(data['amount'])
matter.save()
if matter.has_notify and matter.usage_budget >= matter.budget * (matter.notify_limit / 100):
sendBudgetLimitWarning.delay(matter_id=matter.id)
return expenseEntry
@staticmethod
def Remove(request, _id):
expenseEntry = ExpenseEntry.List(request).get(pk=_id)
expenseEntry.is_removed = True
expenseEntry.save()
Timeline.InsertEvent(lawyerUser=request.lawyerUser,
row=expenseEntry,
action=Timeline.Action.REMOVE,
message=None)
return expenseEntry
@staticmethod
def List(request, inIsRemoved=False):
matterIds = Matter.GetReadableMatters(request.lawyerUser).values_list("id", flat=True)
return ExpenseEntry.objects.filter(Q(matter__id__in=matterIds) | Q(creator__id=request.lawyerUser.id)).filter(
is_removed=inIsRemoved).all()
@shared_task
def sendBudgetLimitWarning(matter_id):
matter = Matter.objects.get(pk=matter_id)
for lawyer in matter.notifications.all():
apps, in_mail = async_to_sync(CheckUserNotification)(user_id=lawyer.id, _type={"app": "is_budget_matter_in_app",
"mobile": "is_budget_matter_in_mobile",
"email": "is_budget_matter_in_email"})
if in_mail:
_msg = Messenger.GenerateMessage(os.path.join(ROOT_DIR, "assets/verifies/part/budget-warning.html"),
tokens={
"lawyer_name": lawyer.first_name + ' ' + lawyer.last_name,
"matter_name": matter.title,
"matter_id": matter.id,
"main_url": BASE_URL,
})
Messenger.SendMail.delay([lawyer.email_address],
message=_msg,
subject='Matter Budget Warning.',
fromEmail=f'Budget Warning <no-reply@ira-lex.com>')
Messenger.SendFirebaseNotification.delay(
title='Matter Budget Warning.',
description=f'Your {matter.title} has been reached to the budget limit.',
lawyerUserId=lawyer.id, apps=apps)
return True

28
activity/serializers.py Normal file
View File

@ -0,0 +1,28 @@
from rest_framework import serializers
from account.views import get_fullname
from activity.models import TimeEntry, ExpenseEntry
class TimeEntrySerializer(serializers.ModelSerializer):
user_name = serializers.SerializerMethodField()
@staticmethod
def get_user_name(obj):
return get_fullname(obj.matter.responsible)
class Meta:
model = TimeEntry
fields = '__all__'
class ExpenseEntrySerializer(serializers.ModelSerializer):
user_name = serializers.SerializerMethodField()
@staticmethod
def get_user_name(obj):
return get_fullname(obj.matter.responsible)
class Meta:
model = ExpenseEntry
fields = '__all__'

3
activity/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

22
activity/urls.py Normal file
View File

@ -0,0 +1,22 @@
from django.urls import path
from activity.views import *
urlpatterns = [
path("time-entry/", CreateTimeEntry),
path("time-entry/<int:_id>/", ByIdTimeEntry),
path("time-entry/query/", QueryTimeEntry),
path("time-entry/category/", CreateTimeEntryCategory),
path("time-entry/category/<int:_id>/", ByIdTimeEntryCategory),
path("time-entry/category/query/", QueryTimeEntryCategory),
path("expense-entry/", CreateExpenseEntry),
path("expense-entry/<int:_id>/", ByIdExpenseEntry),
path("expense-entry/query/", QueryExpenseEntry),
path("expense-entry/category/", CreateExpenseCategory),
path("expense-entry/category/<int:_id>/", ByIdExpenseCategory),
path("expense-entry/category/query/", QueryExpenseCategory),
]

117
activity/views.py Normal file
View File

@ -0,0 +1,117 @@
from django.shortcuts import render
from account.Authentication import Authentication
from activity.models import TimeEntry, ExpenseEntry, ExpenseCategory, TimeEntryCategory
from core.filter_parser.FilterParser import FilterParser
from core.utility.Response import Response
from permission.permission_checker import Permissioner , Permissioner2
from timeline.timeline import Timeline
@Authentication.Authenticate()
@Permissioner.PermisionChecker("activity.time-entry.create")
def CreateTimeEntry(request):
timeEntry = TimeEntry.Create(request)
return Response(timeEntry)
@Authentication.Authenticate()
@Permissioner2.PermisionChecker(["activity.time-entry.get","activity.time-entry.edit","activity.time-entry.delete"])
def ByIdTimeEntry(request, _id):
timeEntry = None
if request.method == "GET":
timeEntry = TimeEntry.List(request).get(pk=_id)
elif request.method == "PUT":
timeEntry = TimeEntry.Update(request, _id)
elif request.method == "DELETE":
timeEntry = TimeEntry.Remove(request, _id)
return Response(timeEntry)
@Authentication.Authenticate()
@Permissioner.PermisionChecker("activity.time-entry.list")
def QueryTimeEntry(request):
return Response(FilterParser(request, TimeEntry.List(request), TimeEntry).Execute())
@Authentication.Authenticate()
def CreateTimeEntryCategory(request):
timeEntryCategory = TimeEntryCategory.Create(request)
return Response(timeEntryCategory)
@Authentication.Authenticate()
def ByIdTimeEntryCategory(request, _id):
timeEntryCategory = None
if request.method == "GET":
timeEntryCategory = TimeEntryCategory.List(request).get(pk=_id)
elif request.method == "PUT":
timeEntryCategory = TimeEntryCategory.Update(request, _id)
elif request.method == "DELETE":
timeEntryCategory = TimeEntryCategory.Remove(request, _id)
return Response(timeEntryCategory)
@Authentication.Authenticate()
def QueryTimeEntryCategory(request):
return Response(FilterParser(request, TimeEntryCategory.List(request), TimeEntryCategory).Execute())
@Authentication.Authenticate()
@Permissioner.PermisionChecker("activity.expense-entry.create")
def CreateExpenseEntry(request):
expenseEntry = ExpenseEntry.Create(request)
return Response(expenseEntry)
@Authentication.Authenticate()
@Permissioner2.PermisionChecker(["activity.expense-entry.get" , "activity.expense-entry.edit" , "activity.expense-entry.delete"])
def ByIdExpenseEntry(request, _id):
expenseEntry = None
if request.method == "GET":
expenseEntry = ExpenseEntry.List(request).get(pk=_id)
elif request.method == "PUT":
expenseEntry = ExpenseEntry.Update(request, _id)
elif request.method == "DELETE":
expenseEntry = ExpenseEntry.Remove(request, _id)
return Response(expenseEntry)
@Authentication.Authenticate()
@Permissioner.PermisionChecker("activity.expense-entry.list")
def QueryExpenseEntry(request):
return Response(FilterParser(request, ExpenseEntry.List(request), ExpenseEntry).Execute())
@Authentication.Authenticate()
@Permissioner.PermisionChecker("activity.expense-entry.category.create")
def CreateExpenseCategory(request):
expenseCategory = ExpenseCategory.Create(request)
return Response(expenseCategory)
@Authentication.Authenticate()
@Permissioner2.PermisionChecker(["activity.expense-entry.category.get" , "activity.expense-entry.category.edit" , "activity.expense-entry.category.delete"])
def ByIdExpenseCategory(request, _id):
expenseCategory = None
if request.method == "GET":
expenseCategory = ExpenseCategory.List(request).get(pk=_id)
elif request.method == "PUT":
expenseCategory = ExpenseCategory.Update(request, _id)
elif request.method == "DELETE":
expenseCategory = ExpenseCategory.Remove(request, _id)
return Response(expenseCategory)
@Authentication.Authenticate()
@Permissioner.PermisionChecker("activity.expense-entry.category.list")
def QueryExpenseCategory(request):
return Response(FilterParser(request, ExpenseCategory.List(request), ExpenseCategory).Execute())

View File

3
administrator/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
administrator/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class AdminConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'administrator'

View File

View File

@ -0,0 +1,26 @@
from hashlib import sha256
from django.core.management import BaseCommand
from account.models import LawyerUser
class Command(BaseCommand):
help = "You can add super admin user with this command"
def add_arguments(self, parser):
parser.add_argument("--email")
parser.add_argument("--password")
parser.add_argument("--first_name")
parser.add_argument("--last_name")
def handle(self, *args, **options):
lawyerUser = LawyerUser.objects.create(
email_address=options["email"],
password=sha256(options["password"].encode("utf-8")).hexdigest(),
first_name=options["first_name"],
last_name=options["last_name"],
is_verified=True,
permission=LawyerUser.Permission.SUPER_ADMIN_PERMISSION)
self.stdout.write(self.style.SUCCESS(f"User {lawyerUser.email_address} created ✅"))

3
administrator/models.py Normal file
View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

3
administrator/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

12
administrator/urls.py Normal file
View File

@ -0,0 +1,12 @@
from django.urls import path
from administrator.views import *
urlpatterns = [
path("user/query/", QueryInUsers),
path("user/query/deleted/", QueryInDeletedUsers),
# path("user/<int:_id>/charge/", ChargeUser),
path("hardware/", Hardware),
path("user/application-admin/", CreateApplicationAdmin)
]

72
administrator/views.py Normal file
View File

@ -0,0 +1,72 @@
from hashlib import sha256
import psutil
from account.Authentication import Authentication
from account.models import LawyerUser
from core.filter_parser.FilterParser import FilterParser
from core.utility.Response import Response
@Authentication.Authenticate()
def QueryInUsers(request):
return Response(FilterParser(request, LawyerUser.objects.all(), LawyerUser).Execute())
#
# @Authentication.Authenticate()
# @Permission.Require(LawyerUser.Permission.APPLICATION_SUPER_ADMIN)
# def ChargeUser(request, _id):
# return Response(Subscription.Charge(request, _id))
@Authentication.Authenticate()
def CreateApplicationAdmin(request):
lawyerUser = LawyerUser.objects.create(
email_address=request.bodyDict["email"],
password=sha256(
request.bodyDict["password"].encode("utf-8")).hexdigest(),
first_name=request.bodyDict["first_name"],
last_name=request.bodyDict["last_name"],
is_verified=True,
# permission=LawyerUser.Permission.SUPER_ADMIN_PERMISSION #TODO : Add permission
)
return Response(lawyerUser)
@Authentication.Authenticate()
def QueryInDeletedUsers(request):
return Response(FilterParser(request, LawyerUser.objects.filter(is_removed=True), LawyerUser).Execute())
@Authentication.Authenticate()
def Hardware(request):
psutilRam = psutil.virtual_memory()
psutilDisk = psutil.disk_usage("/")
ram = {
"total": psutilRam.total,
"used": psutilRam.used,
"percent": psutilRam.percent,
"available": psutilRam.available,
}
cpu = {
"count": psutil.cpu_count(),
"freq": psutil.cpu_freq(),
"percent": psutil.cpu_percent(),
}
disk = {
"total": psutilDisk.total,
"used": psutilDisk.used,
"percent": psutilDisk.percent,
"free": psutilDisk.free,
}
return Response({
"ram": ram,
"cpu": cpu,
"disk": disk
})

View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<h2>Add Facebook Login to your webpage</h2>
<!-- Set the element id for the JSON response -->
<p id="profile"></p>
<script>
document.addEventListener("DOMContentLoaded", function () {
// <!-- FB SDK LOAD START -->
window.fbAsyncInit = function () {
FB.init({
appId: '1333717674102126',
cookie: true,
xfbml: true,
version: 'v18.0'
});
FB.AppEvents.logPageView();
};
(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement(s);
js.id = id;
js.src = "https://connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
// <!-- FB SDK LOAD END -->
});
</script>
</body>
</html>

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>$Title$</title>
</head>
<body>
$END$
</body>
</html>

View File

@ -0,0 +1,173 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Invoice</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet"
id="bootstrap-css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
{style}
</head>
<body style="margin: 0; padding: 0; font-family: 'Montserrat', sans-serif;">
<!-- HEADER -->
<div style="background-image: url('https://ira-lex.com/app/download.png'); width: 100%; height: fit-content">
<div style="text-align: center; color: rgba(0,0,0,.65); font-size: 48px; line-height: 48px; padding: 34px 0; border-bottom: 1px solid #e8e8e8;">
INVOICE {invoice_no}
</div>
</div>
<div>
<!-- TITLE -->
<table style="width: 100%; border-bottom: 1px solid #e8e8e8; padding: 24px 0;">
<tr>
<td style="text-align: left;">
<img
src="{avatar}"
alt="Logo"
style="width: 10rem; object-fit: contain;"
>
</td>
<td style="text-align: right">
<div style="color: #5e615e; font-weight: 400; font-size: 10px; line-height: 1;">Invoice Number:
{invoice_no}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Invoice Date:
{invoice_date}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Payment Due:
{payment_date}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Reference Code:
{reference_code}
</div>
</td>
</tr>
</table>
<!-- DATA -->
<div style="width: 100%; display: flex; align-items: flex-start; justify-content: space-around ;">
<div style="text-align: left; width: 50%;">
<div style="margin-top: 24px; font-weight: 700; line-height: 21px; font-size: 12px;">
{company_name}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Address:
{company_address}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">City: {company_city}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">State:
{company_state}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Post Code:
{company_postalcode}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Country:
{company_country}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Tel:
{company_tel}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Fax: {company_fax}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Email:
{company_mail}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Web: {company_site}
</div>
</div>
<div style="text-align: left ;width: 50%;">
<div style="margin-top: 24px; font-weight: 700; line-height: 21px; font-size: 12px;">Client:
{client_name}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Address:
{client_address}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">City: {client_city}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">State:
{client_state}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Country:
{client_country}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Tel: {client_tel}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Email:
{client_email}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Amount Due:
{amount_due}
</div>
</div>
</div>
<!-- TABLE -->
<table style="width: 100%; margin-top: 8px; border-collapse: collapse;">
<tr style="background-color: #41438d; color: white;">
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Item No.</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Matter</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;word-break: break-all">
Description
</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Qty/Hr</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Unit Price</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Amount</th>
</tr>
{items}
</table>
<!-- FOOTER -->
<div style="margin-left: auto; width: 50%; background-color: #fafafa; padding: 16px;">
<div>
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
Total:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{net_total}
</div>
</div>
<div>
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
Discount:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{discount}
</div>
</div>
<div>
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{sst_amount}% SST:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{sst}
</div>
</div>
<div>
<div style="display: inline-block; width: 49%; text-align: left; font-weight: 700; font-size: 12px; line-height: 1.5;">
Total Amount:
</div>
<div style="display: inline-block; width: 49%; text-align: right; font-weight: 700; font-size: 12px; line-height: 1.5;">
{total}
</div>
</div>
</div>
<!-- NOTES -->
<div id="notes">
<p style="color: #000000d9;font-size: 0.875rem;margin-right: 0.2rem;">Notes:</p>
<div style="color: #000000a6;font-size: 12px;">
{company_description}
</div>
</div> <!-- END NOTES -->
</div>
</body>
</html>

View File

@ -0,0 +1,5 @@
<tr>
<td>{fundRequestDate}</td>
<td>{fundRequestNote}</td>
<td>{fundRequestTotal}</td>
</tr>

View File

@ -0,0 +1,9 @@
<style>
.logo {
background-color: #3a3dbe;
border-radius: 50%;
height: 100px;
width: 100px;
padding: 10px;
}
</style>

5
assets/google-oauth2/.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/google-oauth2.iml" filepath="$PROJECT_DIR$/.idea/google-oauth2.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,27 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="google-signin-client_id"
content="986858475219-461v2efu5b1ghfsofnajak56pt806spa.apps.googleusercontent.com">
<script src="https://apis.google.com/js/platform.js" async defer></script>
<title>Login</title>
</head>
<body>
<div class="g-signin2" data-onsuccess="onSignIn"></div>
<script>
function onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead.
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail()); // This is null if the 'email' scope is not present.
}
</script>
</body>
</html>

View File

@ -0,0 +1,7 @@
<style>
@page {
size: A4;
padding: 0;
margin: 0;
}
</style>

View File

@ -0,0 +1,6 @@
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
Discount:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{discount}
</div>

View File

@ -0,0 +1,166 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Invoice</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet"
id="bootstrap-css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
{style}
</head>
<body>
<div class="container">
<div class="row">
<div class="col-12">
<div class="d-flex">
<div class="card-body p-0">
<div class="row p-5">
<div class="col-md-6">
<!--img class="logo" width="100" height="100" src="https://ira-lex.com/img/iralex-logo.74718d06.svg"-->
<img class="logo" width="100" height="100">
</div>
<div class="col-md-6 text-right">
<p class=" font-weight-bold mb-1">Invoice {invoiceId}</p>
<div class="text-muted">Date: {curDate}</div>
<div class="text-muted">Due On: {dueDate}</div>
</div>
</div>
<hr class="">
<div class="row px-5 pt-4">
<div class="col-md-6">
<p class="h3 font-weight-bold mb-4">{legalName} Legal</p>
<p class="mb-1">Client: {clientName}</p>
<p>Matter(s)</p>
</div>
</div>
<div class="row px-5 pt-4">
<div class="col-md-12">
<table class="table">
<thead>
<tr>
<th class="border-0 text-uppercase small font-weight-bold">Row</th>
<th class="border-0 text-uppercase small font-weight-bold">Title</th>
<th class="border-0 text-uppercase small font-weight-bold">Quantity</th>
<th class="border-0 text-uppercase small font-weight-bold">Hours</th>
<th class="border-0 text-uppercase small font-weight-bold">Total</th>
</tr>
</thead>
<tbody>
{mainRows}
</tbody>
</table>
<div class="d-flex justify-content-end pr-5">
<p class="h5">Total:</p>
<p class="h5 ml-2">{total}</p>
</div>
</div>
</div>
<hr class="mt-5"/>
<!--
<div class="">
<p class="mt-5 h3 font-weight-bold mb-4 px-5">Detailed Statement of Account</p>
<p class="px-5 h4">Other Invoices</p>
<div class="row px-5 pt-4">
<div class="col-md-12">
<table class="table">
<thead>
<tr>
<th class="border-0 text-uppercase small font-weight-bold">Invoice Number</th>
<th class="border-0 text-uppercase small font-weight-bold">Due On</th>
<th class="border-0 text-uppercase small font-weight-bold">Amount Due</th>
<th class="border-0 text-uppercase small font-weight-bold">Payments Received</th>
<th class="border-0 text-uppercase small font-weight-bold">Balance Due</th>
</tr>
</thead>
<tbody>
<tr>
<td>3 </td>
<td>12/21/2021</td>
<td>MR40.00</td>
<td>MR0.00</td>
<td>MR40.00</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="">
<p class="px-5 h4">Current Invoice</p>
<div class="row px-5 pt-4">
<div class="col-md-12">
<table class="table">
<thead>
<tr>
<th class="border-0 text-uppercase small font-weight-bold">Invoice Number</th>
<th class="border-0 text-uppercase small font-weight-bold">Due On</th>
<th class="border-0 text-uppercase small font-weight-bold">Amount Due</th>
<th class="border-0 text-uppercase small font-weight-bold">Payments Received</th>
<th class="border-0 text-uppercase small font-weight-bold">Balance Due</th>
</tr>
</thead>
<tbody>
<tr>
<td>8</td>
<td>12/21/2021</td>
<td>MR220.00</td>
<td>MR0.00</td>
<td>MR22.00</td>
</tr>
</tbody>
</table>
<div class="d-flex justify-content-end pr-5">
<p class="h5">Outstanding Balance:</p>
<p class="h5 ml-2">RM62</p>
</div>
<div class="d-flex justify-content-end pr-5" >
<p class="h5">Total Amount Outstanding:</p>
<p class="h5 ml-2">RM62</p>
</div>
</div>
</div>
</div>
-->
<div class="d-flex flex-col text-white px-5 pt-16 mt-5" style="background: #3a3dbe">
<div class="py-3 px-5">
<div class="mb-2">Please make all amounts payable to: {legalName} Legal</div>
<!--<div class="font-weight-light">Please pay within 30 days.</div>-->
</div>
</div>
</div>
</div>
</div>
</div>
<div class="text-light mt-5 mb-5 text-center small">invoice template by : <a class="text-light" target="_blank"
href="http://totoprayogo.com">totoprayogo.com</a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,7 @@
<tr>
<td>{matterRowNumber}</td>
<td>{matterTitle}</td>
<td>{matterQuantity}</td>
<td>{matterHours}</td>
<td>{matterTotal}</td>
</tr>

View File

@ -0,0 +1,9 @@
<style>
.logo {
background-color: #3a3dbe;
border-radius: 50%;
height: 100px;
width: 100px;
padding: 10px;
}
</style>

View File

@ -0,0 +1,12 @@
<tr>
<td style="padding: 16px; border-bottom: 1px solid #80808030;font-size: 12px !important;">{item_no}</td>
<td style="padding: 16px; border-bottom: 1px solid #80808030;font-size: 12px !important;">{item_matter}</td>
<td style="padding: 16px; border-bottom: 1px solid #80808030;font-size: 12px !important;"><h3>
{item_category}
</h3>
{item_description}
</td>
<td style="padding: 16px; border-bottom: 1px solid #80808030;font-size: 12px !important;">{item_qt}</td>
<td style="padding: 16px; border-bottom: 1px solid #80808030;font-size: 12px !important;">{unit_price}</td>
<td style="padding: 16px; border-bottom: 1px solid #80808030;font-size: 12px !important;">{unit_amount}</td>
</tr>

163
assets/invoices/main_1.html Normal file
View File

@ -0,0 +1,163 @@
<!DOCTYPE html>
<html>
<head>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap">
<title></title>
</head>
<body style="margin: 0; padding-inline: 15px; padding-block: 0; font-family: 'Montserrat', sans-serif;">
<!-- HEADER -->
<div style="background-image: url('https://ira-lex.com/app/download.png'); width: 100%; height: fit-content">
<div style="text-align: center; color: rgba(0,0,0,.65); font-size: 48px; line-height: 48px; padding: 34px 0; border-bottom: 1px solid #e8e8e8;">
{title} {invoice_no}
</div>
</div>
<div>
<!-- TITLE -->
<table style="width: 100%; border-bottom: 1px solid #e8e8e8; padding: 24px 0;">
<tr>
<td style="text-align: left;">
<img
src="{avatar}"
alt="Logo"
style="width: 10rem; object-fit: fill;"
>
</td>
<td style="text-align: right">
<div style="color: #5e615e; font-weight: 400; font-size: 10px; line-height: 1;">{type} Number:
{invoice_no}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">{type} Date:
{invoice_date}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Payment Due:
{payment_date}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Our Reference:
{reference_code}
</div>
</td>
</tr>
</table>
<!-- DATA -->
<div style="width: 100%; display: flex; align-items: flex-start; justify-content: space-around ;">
<div style="text-align: left; width: 50%;">
<div style="margin-top: 24px; font-weight: 700; line-height: 21px; font-size: 12px;">
{company_name}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Address:
{company_address}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">City: {company_city}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">State:
{company_state}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Post Code:
{company_postalcode}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Country:
{company_country}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Tel:
{company_tel}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Fax: {company_fax}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Email:
{company_mail}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Web: {company_site}
</div>
</div>
<div style="text-align: left ;width: 50%;">
<div style="margin-top: 24px; font-weight: 700; line-height: 21px; font-size: 12px;">{Client_title}:
{client_name}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Address:
{client_address}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">City: {client_city}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">State:
{client_state}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Country:
{client_country}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Tel: {client_tel}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Email:
{client_email}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Amount Due:
{amount_due}
</div>
</div>
</div>
<!-- TABLE -->
<table style="width: 100%; margin-top: 8px; border-collapse: collapse;">
<tr style="background-color: #41438d; color: white;">
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Item No.</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Matter</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;word-break: break-all">
Description
</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Qty/Hr</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Unit Price</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Amount</th>
</tr>
{items}
</table>
<!-- FOOTER -->
<div style="margin-left: auto; width: 50%; background-color: #fafafa; padding: 16px;">
<div>
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
Total:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{net_total}
</div>
</div>
<div>
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
Discount:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{discount}
</div>
</div>
<div>
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{sst_amount}% SST:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{sst}
</div>
</div>
<div>
<div style="display: inline-block; width: 49%; text-align: left; font-weight: 700; font-size: 12px; line-height: 1.5;">
Total Amount:
</div>
<div style="display: inline-block; width: 49%; text-align: right; font-weight: 700; font-size: 12px; line-height: 1.5;">
{total}
</div>
</div>
</div>
<!-- NOTES -->
<div id="notes">
<p style="color: #000000d9;font-size: 0.875rem;margin-right: 0.2rem;">Notes:</p>
<div style="color: #000000a6;font-size: 12px;">
{company_description}
</div>
</div> <!-- END NOTES -->
</div>
</body>
</html>

178
assets/invoices/main_2.html Executable file
View File

@ -0,0 +1,178 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap">
<meta charset="UTF-8">
<title></title>
</head>
<body style="font-family: 'Montserrat', sans-serif;">
<!-- HEADER -->
<table style="color: white; border-collapse: collapse; border-spacing: 0; width: 100%;">
<clogroup>
<col style="background: #41438d;">
<col style="background: #393a87;">
</clogroup>
<tr>
<td style=" font-weight: 500;margin: 5rem; font-size: 1.875rem; padding: 1rem 0 0.75rem 2rem;">
{title} {invoice_no}
</td>
<td style="text-align: center; width: 30%; margin-top:7rem" rowspan="2">
<small>Amount Due</small>
<p style="text-align: center; font-size: 1.5rem; font-weight: 500;">
{amount_due}
</p>
</td>
</tr>
<tr>
<td style="line-height: 1.5; padding: 0 0 1rem 2rem; font-weight: 500;">
<small>{client_name}</small>
</td>
</tr>
</table> <!-- END HEADER -->
<!-- BODY -->
<section style="padding: 1.5rem;">
<!-- INVOICE INFO -->
<table style="border-collapse: collapse;border-spacing: 0;width: 100%;">
<tr>
<td style="width: 50%;">
<span style="color: #000000d9;font-size: 0.875rem;margin-right: 0.2rem;">{type} Number: </span>
<span style="color: #000000a6;font-size: 0.875rem;">{invoice_no}</span>
</td>
<td>
<span style="color: #000000d9;font-size: 0.875rem;margin-right: 0.2rem;">{type} Date: </span>
<span style="color: #000000a6;font-size: 0.875rem;">{invoice_date}</span>
</td>
</tr>
<tr>
<td>
<span style="color: #000000d9;font-size: 0.875rem;margin-right: 0.2rem;">Payment Due: </span>
<span style="color: #000000a6;font-size: 0.875rem;">{payment_date}</span>
</td>
<td>
<span style="color: #000000d9;font-size: 0.875rem;margin-right: 0.2rem;">Our Reference: </span>
<span style="color: #000000a6;font-size: 0.875rem;">{reference_code}</span>
</td>
</tr>
</table> <!-- END INVOICE INFO -->
<hr>
<!-- DATA -->
<table style="margin-bottom: 1rem;border-collapse: collapse;border-spacing: 0;width: 100%;">
<tr>
<td style="width: 50%;">
<div style="color: #5e615e; line-height: 21px; font-weight: 700; font-size: 14px;">{company_name}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">Address: {company_address}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">City: {company_city}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">State: {company_state}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">Post Code: {company_postalcode}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">Country: {company_country}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">Tel: {company_tel}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">Fax: {company_fax}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">Email: {company_mail}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">Web: {company_site}</div>
</td>
<td style="vertical-align: top;">
<div style="color: #5e615e; line-height: 21px; font-weight: 700; font-size: 14px;">{Client_title}:
{client_name}
</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">Address: {client_address}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">City: {client_city}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">State: {client_state}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">Country: {client_country}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">Tel: {client_tel}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">Email: {client_email}</div>
<div style="color: #5e615e; font-size: 12px; line-height: 1.5;">Amount Due: {amount_due}</div>
</td>
</tr>
</table> <!-- END DATA -->
<!-- TABLE -->
<table id="main-table"
style="width: 100%; margin-top: 8px; border-collapse: collapse;padding: 12px; border-bottom: 1px solid #80808030;">
<tr style="background-color: #41438d; color: white;">
<th style="text-align: left; font-size: 12px;">Item No.</th>
<th style="text-align: left; font-size: 12px;">Matter</th>
<th style="text-align: left; font-size: 12px; word-break: break-all">Description</th>
<th style="text-align: left;font-size: 12px;">Qty/Hr</th>
<th style="text-align: left; font-size: 12px;">Unit Price</th>
<th style="text-align: left; font-size: 12px;">Amount</th>
</tr>
{items}
</table> <!-- END TABLE -->
<!-- TABLE FOOTER -->
<div style="margin-left: auto; width: 50%; background-color: #fafafa; padding: 16px;">
<div>
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 14px; line-height: 1.5;">
Total:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 14px; line-height: 1.5;">
{net_total}
</div>
</div>
<div>
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 14px; line-height: 1.5;">
Discount:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 14px; line-height: 1.5;">
{discount}
</div>
</div>
<div>
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 14px; line-height: 1.5;">
{sst_amount}% SST:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 14px; line-height: 1.5;">
{sst}
</div>
</div>
<div>
<div style="display: inline-block; width: 49%; text-align: left; font-weight: 700; font-size: 14px; line-height: 1.5;">
Total Amount:
</div>
<div style="display: inline-block; width: 49%; text-align: right; font-weight: 700; font-size: 14px; line-height: 1.5;">
{total}
</div>
</div>
</div> <!-- END TABLE FOOTER -->
<!-- NOTES -->
<div id="notes">
<p style="color: #000000d9;font-size: 0.875rem;margin-right: 0.2rem;">Notes:</p>
<div style="color: #000000a6;font-size: 12px;">
{company_description}
</div>
</div> <!-- END NOTES -->
<hr>
<!-- FOOTER -->
<table style="border-collapse: collapse;border-spacing: 0;width: 100%;">
<tr>
<td>
<img src="{avatar}" alt="Logo" style="width: 6rem; object-fit:fill; margin-right: 10px">
</td>
<td>
<p style="color: #000000d9;font-size: 0.875rem;margin-right: 0.2rem;padding-left:1rem">
{company_name}</p>
<p style="color: #000000a6;font-size: 0.575rem; padding-left: 1rem ">{company_address}</p>
</td>
<td>
<p style="color: #000000d9;font-size: 0.875rem;margin-right: 0.2rem;">Contact Information</p>
<p style="color: #000000a6;font-size: 0.575rem;">{company_tel}</p>
<p style="color: #000000a6;font-size: 0.575rem;">{company_mail}</p>
</td>
</tr>
</table> <!-- END FOOTER -->
</section> <!-- END BODY -->
</body>
</html>

198
assets/invoices/main_3.html Executable file
View File

@ -0,0 +1,198 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap">
<meta charset="UTF-8">
<title></title>
</head>
<body style="margin: 0; padding: 0; font-family: 'Montserrat', sans-serif;">
<div style="display: flex; flex-direction: row; ">
<div style="background-image: url('https://ira-lex.com/app/temHeader.png'); background-repeat: no-repeat;background-size: cover; color: white; display: flex; justify-content: center ;width: 100%; height: fit-content">
<p> {title} {invoice_no}</p>
</div>
</div>
<div>
<!-- TITLE -->
<div style="width: 100%; display: flex; align-items: flex-start; justify-content: space-around; margin-top: 3rem;">
<div style="text-align: left; width: 50%;">
<img
src="{avatar}"
alt="Logo"
style="width: 10rem; object-fit: fill;"
>
</div>
<div style="text-align: left; width: 50%;">
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{company_name}
</div>
<div>
{company_address}
</div>
<div>
{company_tel}
</div>
<div>
{company_site}
</div>
</div>
</div>
<div style="position: relative; margin: 3rem 0;">
<div style="background: rgba(0,0,0,.1); width: 100%; height: 3px; position: absolute; top: 50%;">
<!-- box-shadow: 0 2px 4px 0 rgba(0,0,0,.1) !important; -->
</div>
<div style="position: relative; width: 6rem; height: 6rem; margin: 0 auto; border-radius: 50%; background: #fff;">
<!-- box-shadow: 0 2px 4px #999 -->
<div style="margin: 0.25rem; border-radius: 50%; border: 1px dashed #3a3dbe;">
<!-- box-shadow: 0 2px 4px #999; -->
<span style="display: block; text-align: center; margin: 2.25rem auto;">{type}</span>
</div>
</div>
</div>
<div style="padding: 0 3rem; margin-top: 4rem;">
<div style="width: 100%; display: flex; align-items: flex-start; justify-content: space-around ;">
<div style="text-align: left; width: 50%;">
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5">
{type} number : {invoice_no}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Payment Due:
{payment_date}
</div>
</div>
<div style="text-align: left; width: 50%;">
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">{type} Date:
{invoice_date}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Our Reference:
{reference_code}
</div>
</div>
</div>
<div style="height: 1px; background: #e8e8e8; margin: 24px 0;"></div>
<!-- DATA -->
<div style="width: 100%; display: flex; align-items: flex-start; justify-content: space-around ;">
<div style="text-align: left; width: 50%;">
<div style="margin-top: 24px; font-weight: 700; line-height: 21px; font-size: 12px;">
{company_name}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Address:
{company_address}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">City: {company_city}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">State:
{company_state}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Post Code:
{company_postalcode}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Country:
{company_country}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Tel:
{company_tel}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Fax: {company_fax}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Email:
{company_mail}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Web: {company_site}
</div>
</div>
<div style="text-align: left ;width: 50%;">
<div style="margin-top: 24px; font-weight: 700; line-height: 21px; font-size: 12px;">{Client_title}:
{client_name}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Address:
{client_address}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">City: {client_city}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">State:
{client_state}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Country:
{client_country}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Tel: {client_tel}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Email:
{client_email}
</div>
<div style="color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">Amount Due:
{amount_due}
</div>
</div>
</div>
<!-- TABLE -->
<table style="width: 100%; margin-top: 8px; border-collapse: collapse;">
<tr style="background-color: #41438d; color: white;">
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Item No.</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Matter</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;word-break: break-all">
Description
</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Qty/Hr</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Unit Price</th>
<th style="text-align: left; padding: 10px 12px;font-size: 12px !important;">Amount</th>
</tr>
{items}
</table>
<!-- FOOTER -->
<div style="margin-left: auto; width: 50%; background-color: #fafafa; padding: 16px;">
<div>
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
Total:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{net_total}
</div>
</div>
<div>
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
Discount:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{discount}
</div>
</div>
<div>
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{sst_amount}% SST:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{sst}
</div>
</div>
<div>
<div style="display: inline-block; width: 49%; text-align: left; font-weight: 700; font-size: 12px; line-height: 1.5;">
Total Amount:
</div>
<div style="display: inline-block; width: 49%; text-align: right; font-weight: 700; font-size: 12px; line-height: 1.5;">
{total}
</div>
</div>
</div>
<!-- NOTES -->
<div id="notes">
<p style="color: #000000d9;font-size: 0.875rem;margin-right: 0.2rem;">Notes:</p>
<div style="color: #000000a6;font-size: 12px;">
{company_description}
</div>
</div> <!-- END NOTES -->
</div>
</body>
</html>

62
assets/invoices/receipt.html Executable file
View File

@ -0,0 +1,62 @@
<!DOCTYPE html>
<html>
<head>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap">
</head>
<body style="margin: 0; padding: 0; font-family: 'Montserrat', sans-serif;">
<img src="{avatar}" alt="Logo" style="object-fit: contain; width: 10rem; height: 65px; display: block; margin: 0 auto;">
<h4 style="text-align: center; font-weight: 700; color: #000000a6;">{company_name}</h4>
<h5 style="max-width: 500px; text-align: center; margin: 0 auto; color: #000000a6;">{company_address}</h5>
<table style="width: 100%;">
<tr>
<td style="text-align: center; width: 50%; font-size: 14px; color: #000000a6;">
Email: {company_mail}
</td>
<td style="text-align: center; width: 50%; font-size: 14px; color: #000000a6;">
Tel: {company_tel}
</td>
</tr>
</table>
<h3 style="margin-top: 2.5rem; margin-bottom: 0.5rem; text-align: center;">OFFICIAL RECEIPT</h3>
<!-- DATA -->
<table style="width: 100%; margin-bottom: 1rem;">
<tr>
<td style="width: 70%;">
<div style="color: #5e615e; line-height: 21px; font-weight: 700; font-size: 14px;">Received From:
{receive_from}
</div>
<div style="color: #5e615e; font-size: 14px; line-height: 1.5;">{client_address1}</div>
<div style="color: #5e615e; font-size: 14px; line-height: 1.5;">{client_address2}</div>
<div style="color: #5e615e; font-size: 14px; line-height: 1.5;">Payment For: Invoice {invoice_no}</div>
<div style="color: #5e615e; font-size: 14px; line-height: 1.5;">Remark: {remark}</div>
</td>
<td style="padding-left: 0.25rem; width: 30%; vertical-align: top;">
<div style="color: #5e615e; font-size: 14px; line-height: 1.5;">Receipt No: OR00{receipt_no}</div>
<div style="color: #5e615e; font-size: 14px; line-height: 1.5;">Date: {receipt_date}</div>
<div style="color: #5e615e; font-size: 14px; line-height: 1.5;">Payment Type: {payment_type}</div>
<div style="color: #5e615e; font-size: 14px; line-height: 1.5;">Bank in Date: {receipt_bank_date}</div>
<div style="color: #5e615e; font-size: 14px; line-height: 1.5;">Amount :{amount}</div>
</td>
</tr>
</table> <!-- END DATA -->
<!-- Price -->
<hr style="margin-top: 40px;">
<div style="margin-top: 1.2rem; display: inline-flex; justify-content: space-between;">
<div style="">{char_amount}</div>
<div style="display: inline-flex;"><div style="font-weight: bold;">Amount :</div>
<div>{amount}</div>
</div>
</div>
</body>
</html>

6
assets/invoices/tax.html Normal file
View File

@ -0,0 +1,6 @@
<div style="display: inline-block; width: 49%; text-align: left; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{sst_amount}% SST:
</div>
<div style="display: inline-block; width: 49%; text-align: right; color: #5e615e; font-weight: 400; font-size: 12px; line-height: 1.5;">
{sst}
</div>

View File

@ -0,0 +1,340 @@
<style>
/* What it does: Remove spaces around the email design added by some email clients. */
/* Beware: It can remove the padding / margin and add a background color to the compose a reply window. */
html,
body {
margin: 0 auto !important;
padding: 0 !important;
height: 100% !important;
width: 100% !important;
background: #f1f1f1;
}
/* What it does: Stops email clients resizing small text. */
* {
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
/* What it does: Centers email on Android 4.4 */
div[style*="margin: 16px 0"] {
margin: 0 !important;
}
/* What it does: Stops Outlook from adding extra spacing to tables. */
table,
td {
mso-table-lspace: 0pt !important;
mso-table-rspace: 0pt !important;
}
/* What it does: Fixes webkit padding issue. */
table {
border-spacing: 0 !important;
border-collapse: collapse !important;
table-layout: fixed !important;
margin: 0 auto !important;
}
/* What it does: Uses a better rendering method when resizing images in IE. */
img {
-ms-interpolation-mode: bicubic;
}
/* What it does: Prevents Windows 10 Mail from underlining links despite inline CSS. Styles for underlined links should be inline. */
a {
text-decoration: none;
}
/* What it does: A work-around for email clients meddling in triggered links. */
*[x-apple-data-detectors],
/* iOS */
.unstyle-auto-detected-links *,
.aBn {
border-bottom: 0 !important;
cursor: default !important;
color: inherit !important;
text-decoration: none !important;
font-size: inherit !important;
font-family: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
}
/* What it does: Prevents Gmail from displaying a download button on large, non-linked images. */
.a6S {
display: none !important;
opacity: 0.01 !important;
}
/* What it does: Prevents Gmail from changing the text color in conversation threads. */
.im {
color: inherit !important;
}
/* If the above doesn't work, add a .g-img class to any image in question. */
img.g-img + div {
display: none !important;
}
/* What it does: Removes right gutter in Gmail iOS app: https://github.com/TedGoas/Cerberus/issues/89 */
/* Create one of these media queries for each additional viewport size you'd like to fix */
/* iPhone 4, 4S, 5, 5S, 5C, and 5SE */
@media only screen and (min-device-width: 320px) and (max-device-width: 374px) {
u ~ div .email-container {
min-width: 320px !important;
}
}
/* iPhone 6, 6S, 7, 8, and X */
@media only screen and (min-device-width: 375px) and (max-device-width: 413px) {
u ~ div .email-container {
min-width: 375px !important;
}
}
/* iPhone 6+, 7+, and 8+ */
@media only screen and (min-device-width: 414px) {
u ~ div .email-container {
min-width: 414px !important;
}
}
.primary {
background: #30e3ca;
}
.bg_white {
background: #ffffff;
}
.bg_light {
background: #fafafa;
}
.bg_black {
background: #000000;
}
.bg_dark {
background: rgba(0, 0, 0, .8);
}
.email-section {
padding: 2.5em;
}
/*BUTTON*/
.btn {
padding: 10px 15px;
display: inline-block;
}
.btn.btn-primary {
border-radius: 5px;
background: #3a3dbe;
color: #ffffff;
}
.btn.btn-white {
border-radius: 5px;
background: #ffffff;
color: #000000;
}
.btn.btn-white-outline {
border-radius: 5px;
background: transparent;
border: 1px solid #fff;
color: #fff;
}
.btn.btn-black-outline {
border-radius: 0px;
background: transparent;
border: 2px solid #000;
color: #000;
font-weight: 700;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: 'Lato', sans-serif;
color: #000000;
margin-top: 0;
font-weight: 400;
}
body {
font-family: 'Lato', sans-serif;
font-weight: 400;
font-size: 15px;
line-height: 1.8;
color: rgba(0, 0, 0, .4);
}
a {
color: #30e3ca;
}
table {
}
/*LOGO*/
.logo h1 {
margin: 0;
}
.logo h1 a {
color: #30e3ca;
font-size: 24px;
font-weight: 700;
font-family: 'Lato', sans-serif;
}
/*HERO*/
.hero {
position: relative;
z-index: 0;
}
.hero .text {
color: rgba(0, 0, 0, .3);
}
.hero .text h2 {
color: #000;
font-size: 40px;
margin-bottom: 0;
font-weight: 400;
line-height: 1.4;
}
.hero .text h3 {
font-size: 24px;
font-weight: 300;
}
.hero .text h2 span {
font-weight: 600;
color: #30e3ca;
}
/*HEADING SECTION*/
.heading-section {
}
.heading-section h2 {
color: #000000;
font-size: 28px;
margin-top: 0;
line-height: 1.4;
font-weight: 400;
}
.heading-section .subheading {
margin-bottom: 20px !important;
display: inline-block;
font-size: 13px;
text-transform: uppercase;
letter-spacing: 2px;
color: rgba(0, 0, 0, .4);
position: relative;
}
.heading-section .subheading::after {
position: absolute;
left: 0;
right: 0;
bottom: -10px;
content: '';
width: 100%;
height: 2px;
background: #30e3ca;
margin: 0 auto;
}
.heading-section-white {
color: rgba(255, 255, 255, .8);
}
.heading-section-white h2 {
font-family: line-height: 1;
padding-bottom: 0;
}
.heading-section-white h2 {
color: #ffffff;
}
.heading-section-white .subheading {
margin-bottom: 0;
display: inline-block;
font-size: 13px;
text-transform: uppercase;
letter-spacing: 2px;
color: rgba(255, 255, 255, .4);
}
ul.social {
padding: 0;
}
ul.social li {
display: inline-block;
margin-right: 10px;
}
/*FOOTER*/
.footer {
border-top: 1px solid rgba(0, 0, 0, .05);
color: rgba(0, 0, 0, .5);
}
.footer .heading {
color: #000;
font-size: 20px;
}
.footer ul {
margin: 0;
padding: 0;
}
.footer ul li {
list-style: none;
margin-bottom: 10px;
}
.footer ul li a {
color: rgba(0, 0, 0, 1);
}
@media screen and (max-width: 500px) {
}
</style>

View File

@ -0,0 +1,143 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8">
<!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width">
<!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting">
<!-- Disable auto-scale in iOS 10 Mail entirely -->
<title>IRALEX email</title>
<!-- The title tag shows in email notifications, like Android 4.4. -->
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
</head>
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
<center style="width: 100%; background-color: #f1f1f1;">
<div style="display: none; font-size: 1px;max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden; mso-hide: all; font-family: sans-serif;">
&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;
</div>
<div style="max-width: 600px; margin: 0 auto;" class="email-container">
<!-- BEGIN BODY -->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="logo" style="text-align: center;">
<h1>
<a href="#">
<img src="https://ci3.googleusercontent.com/proxy/x3ocY0ISnAVX5bLWQ_SFLMFkuW31hX5OPBfAfUqnEvtjgsI8O-4XtrVut9XyZE0KrbVtdS8Bj0dIhQ=s0-d-e1-ft#https://app.ira-lex.com/assets/logo.png"
alt=""
style="width: 100px; max-width: 600px; height: auto; margin: auto; display: block;">
</a>
</h1>
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 3em 0 2em 0;">
<img src="https://ci4.googleusercontent.com/proxy/UMF8BOFy2GQHbjvPAShH5Ian8v99R82HSxMPaVI5tyeGwMWS9LjetVHiAZDMw3gXHGSAQd3dnQrlX00=s0-d-e1-ft#https://app.ira-lex.com/assets/email.png"
alt="" style="width: 300px; max-width: 600px; height: auto; margin: auto; display: block;">
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
<table>
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<!--<h2>You are nearly there!</h2> -->
<p> the new user <b>{name}</b> is here in with this phone number {phone} and this email
{email}</p>
<!-- <p><a href="#" class="btn btn-primary">CONFIRM EMAIL</a></p> -->
</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<!-- 1 Column Text + Button : END -->
</table>
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="bg_light footer email-section">
<table>
<tr>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-right: 10px;">
<h3 class="heading">About</h3>
<p>IRALEX is a comprehensive legal practice management software designed to
help lawfirms handle day-to-day operations efficiently.</p>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 5px; padding-right: 5px;">
<h3 class="heading">Contact Info</h3>
<ul>
<li><span class="text"><a href="https://goo.gl/maps/d7KHzKSme9yZ16Ds9">2B-5-8, Block B, Plaza Mont Kiara, No. 2, Jalan Kiara, Mont Kiara, 50480 Kuala Lumpur, Malaysia</a></span>
</li>
<li><span class="text"><a
href="tel:+601128018817">+6011 2801 8817</a></span></li>
<li><span class="text"><a href="mailto:info@ira-lex.com">info@ira-lex.com</a></span>
</li>
</ul>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 10px;">
<h3 class="heading">Useful Links</h3>
<ul>
<li><a href="https://ira-lex.com/">Home</a></li>
<li><a href="https://ira-lex.com/aboutus">About</a></li>
<li><a href="https://ira-lex.com/app/register">Sign Up</a></li>
<li><a href="https://ira-lex.com/app/login">Login</a></li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- end: tr -->
<tr>
<td class="bg_light" style="text-align: center;">
</td>
</tr>
</table>
</div>
</center>
</body>
</html>

View File

@ -0,0 +1,340 @@
<style>
/* What it does: Remove spaces around the email design added by some email clients. */
/* Beware: It can remove the padding / margin and add a background color to the compose a reply window. */
html,
body {
margin: 0 auto !important;
padding: 0 !important;
height: 100% !important;
width: 100% !important;
background: #f1f1f1;
}
/* What it does: Stops email clients resizing small text. */
* {
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
/* What it does: Centers email on Android 4.4 */
div[style*="margin: 16px 0"] {
margin: 0 !important;
}
/* What it does: Stops Outlook from adding extra spacing to tables. */
table,
td {
mso-table-lspace: 0pt !important;
mso-table-rspace: 0pt !important;
}
/* What it does: Fixes webkit padding issue. */
table {
border-spacing: 0 !important;
border-collapse: collapse !important;
table-layout: fixed !important;
margin: 0 auto !important;
}
/* What it does: Uses a better rendering method when resizing images in IE. */
img {
-ms-interpolation-mode: bicubic;
}
/* What it does: Prevents Windows 10 Mail from underlining links despite inline CSS. Styles for underlined links should be inline. */
a {
text-decoration: none;
}
/* What it does: A work-around for email clients meddling in triggered links. */
*[x-apple-data-detectors],
/* iOS */
.unstyle-auto-detected-links *,
.aBn {
border-bottom: 0 !important;
cursor: default !important;
color: inherit !important;
text-decoration: none !important;
font-size: inherit !important;
font-family: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
}
/* What it does: Prevents Gmail from displaying a download button on large, non-linked images. */
.a6S {
display: none !important;
opacity: 0.01 !important;
}
/* What it does: Prevents Gmail from changing the text color in conversation threads. */
.im {
color: inherit !important;
}
/* If the above doesn't work, add a .g-img class to any image in question. */
img.g-img + div {
display: none !important;
}
/* What it does: Removes right gutter in Gmail iOS app: https://github.com/TedGoas/Cerberus/issues/89 */
/* Create one of these media queries for each additional viewport size you'd like to fix */
/* iPhone 4, 4S, 5, 5S, 5C, and 5SE */
@media only screen and (min-device-width: 320px) and (max-device-width: 374px) {
u ~ div .email-container {
min-width: 320px !important;
}
}
/* iPhone 6, 6S, 7, 8, and X */
@media only screen and (min-device-width: 375px) and (max-device-width: 413px) {
u ~ div .email-container {
min-width: 375px !important;
}
}
/* iPhone 6+, 7+, and 8+ */
@media only screen and (min-device-width: 414px) {
u ~ div .email-container {
min-width: 414px !important;
}
}
.primary {
background: #30e3ca;
}
.bg_white {
background: #ffffff;
}
.bg_light {
background: #fafafa;
}
.bg_black {
background: #000000;
}
.bg_dark {
background: rgba(0, 0, 0, .8);
}
.email-section {
padding: 2.5em;
}
/*BUTTON*/
.btn {
padding: 10px 15px;
display: inline-block;
}
.btn.btn-primary {
border-radius: 5px;
background: #3a3dbe;
color: #ffffff;
}
.btn.btn-white {
border-radius: 5px;
background: #ffffff;
color: #000000;
}
.btn.btn-white-outline {
border-radius: 5px;
background: transparent;
border: 1px solid #fff;
color: #fff;
}
.btn.btn-black-outline {
border-radius: 0px;
background: transparent;
border: 2px solid #000;
color: #000;
font-weight: 700;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: 'Lato', sans-serif;
color: #000000;
margin-top: 0;
font-weight: 400;
}
body {
font-family: 'Lato', sans-serif;
font-weight: 400;
font-size: 15px;
line-height: 1.8;
color: rgba(0, 0, 0, .4);
}
a {
color: #30e3ca;
}
table {
}
/*LOGO*/
.logo h1 {
margin: 0;
}
.logo h1 a {
color: #30e3ca;
font-size: 24px;
font-weight: 700;
font-family: 'Lato', sans-serif;
}
/*HERO*/
.hero {
position: relative;
z-index: 0;
}
.hero .text {
color: rgba(0, 0, 0, .3);
}
.hero .text h2 {
color: #000;
font-size: 40px;
margin-bottom: 0;
font-weight: 400;
line-height: 1.4;
}
.hero .text h3 {
font-size: 24px;
font-weight: 300;
}
.hero .text h2 span {
font-weight: 600;
color: #30e3ca;
}
/*HEADING SECTION*/
.heading-section {
}
.heading-section h2 {
color: #000000;
font-size: 28px;
margin-top: 0;
line-height: 1.4;
font-weight: 400;
}
.heading-section .subheading {
margin-bottom: 20px !important;
display: inline-block;
font-size: 13px;
text-transform: uppercase;
letter-spacing: 2px;
color: rgba(0, 0, 0, .4);
position: relative;
}
.heading-section .subheading::after {
position: absolute;
left: 0;
right: 0;
bottom: -10px;
content: '';
width: 100%;
height: 2px;
background: #30e3ca;
margin: 0 auto;
}
.heading-section-white {
color: rgba(255, 255, 255, .8);
}
.heading-section-white h2 {
font-family: line-height: 1;
padding-bottom: 0;
}
.heading-section-white h2 {
color: #ffffff;
}
.heading-section-white .subheading {
margin-bottom: 0;
display: inline-block;
font-size: 13px;
text-transform: uppercase;
letter-spacing: 2px;
color: rgba(255, 255, 255, .4);
}
ul.social {
padding: 0;
}
ul.social li {
display: inline-block;
margin-right: 10px;
}
/*FOOTER*/
.footer {
border-top: 1px solid rgba(0, 0, 0, .05);
color: rgba(0, 0, 0, .5);
}
.footer .heading {
color: #000;
font-size: 20px;
}
.footer ul {
margin: 0;
padding: 0;
}
.footer ul li {
list-style: none;
margin-bottom: 10px;
}
.footer ul li a {
color: rgba(0, 0, 0, 1);
}
@media screen and (max-width: 500px) {
}
</style>

View File

@ -0,0 +1,150 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8">
<!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width">
<!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting">
<!-- Disable auto-scale in iOS 10 Mail entirely -->
<title>IRALEX email</title>
<!-- The title tag shows in email notifications, like Android 4.4. -->
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
</head>
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
<center style="width: 100%; background-color: #f1f1f1;">
<div style="display: none; font-size: 1px;max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden; mso-hide: all; font-family: sans-serif;">
&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;
</div>
<div style="max-width: 600px; margin: 0 auto;" class="email-container">
<!-- BEGIN BODY -->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="logo" style="text-align: center;">
<h1>
<a href="#">
<img src="https://ci3.googleusercontent.com/proxy/x3ocY0ISnAVX5bLWQ_SFLMFkuW31hX5OPBfAfUqnEvtjgsI8O-4XtrVut9XyZE0KrbVtdS8Bj0dIhQ=s0-d-e1-ft#https://app.ira-lex.com/assets/logo.png"
alt=""
style="width: 100px; max-width: 600px; height: auto; margin: auto; display: block;">
</a>
</h1>
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 3em 0 2em 0;">
<img src="https://ci4.googleusercontent.com/proxy/UMF8BOFy2GQHbjvPAShH5Ian8v99R82HSxMPaVI5tyeGwMWS9LjetVHiAZDMw3gXHGSAQd3dnQrlX00=s0-d-e1-ft#https://app.ira-lex.com/assets/email.png"
alt="" style="width: 300px; max-width: 600px; height: auto; margin: auto; display: block;">
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
<table>
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<h2>You are nearly there!</h2>
<p id="fullName">
Hi {name}
</p>
<p>
To finish setting up your account and start using IRALEX, confirm weve
got the correct email for you.
</p>
<p><a href="{verifyLink}" class="btn btn-primary"
style="background: #0000EE; color: #FFFFFF; border-radius: 10px; text-decoration: none; padding: 15px;">
Verify your email</a></p>
</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<!-- 1 Column Text + Button : END -->
</table>
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="bg_light footer email-section">
<table>
<tr>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-right: 10px;">
<h3 class="heading">About</h3>
<p>IRALEX is a comprehensive legal practice management software designed to
help lawfirms handle day-to-day operations efficiently.</p>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 5px; padding-right: 5px;">
<h3 class="heading">Contact Info</h3>
<ul>
<li><span class="text"><a href="https://goo.gl/maps/d7KHzKSme9yZ16Ds9">2B-5-8, Block B, Plaza Mont Kiara, No. 2, Jalan Kiara, Mont Kiara, 50480 Kuala Lumpur, Malaysia</a></span>
</li>
<li><span class="text"><a
href="tel:+601128018817">+6011 2801 8817</a></span></li>
<li><span class="text"><a href="mailto:info@ira-lex.com">info@ira-lex.com</a></span>
</li>
</ul>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 10px;">
<h3 class="heading">Useful Links</h3>
<ul>
<li><a href="https://ira-lex.com/">Home</a></li>
<li><a href="https://ira-lex.com/aboutus">About</a></li>
<li><a href="https://ira-lex.com/app/register">Sign Up</a></li>
<li><a href="https://ira-lex.com/app/login">Login</a></li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- end: tr -->
<tr>
<td class="bg_light" style="text-align: center;">
</td>
</tr>
</table>
</div>
</center>
</body>
</html>

View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8">
<!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width">
<!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting">
<!-- Disable auto-scale in iOS 10 Mail entirely -->
<title>IRALEX email</title>
<!-- The title tag shows in email notifications, like Android 4.4. -->
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
</head>
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
<center style="width: 100%; background-color: #f1f1f1;">
{content}
</center>
</body>
</html>

View File

@ -0,0 +1,56 @@
<style>
body {
font-family: 'Nunito', sans-serif;
}
.container {
margin-left: auto;
margin-right: auto;
width: 1200px;
}
.container img {
text-align: center;
display: block;
margin: 0 auto;
}
.verify, .logo {
margin-top: 5em !important;
}
.header {
font-size: 18px;
font-weight: bold;
}
.body, #fullName {
font-size: 16px;
}
.btn_verify {
background-color: #2a2899;
border-radius: 4px;
padding: 8px;
outline: none;
cursor: pointer;
transition: 0.5s ease;
border: none;
}
.btn_verify:hover {
opacity: 0.8;
transition: 0.5s ease;
}
.footer {
font-size: 12px;
text-align: center;
display: block;
margin: auto;
}
.logo_footer {
margin-top: 2em !important;
}
</style>

View File

@ -0,0 +1,151 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8">
<!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width">
<!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting">
<!-- Disable auto-scale in iOS 10 Mail entirely -->
<title>IRALEX email</title>
<!-- The title tag shows in email notifications, like Android 4.4. -->
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
</head>
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
<center style="width: 100%; background-color: #f1f1f1;">
<div style="display: none; font-size: 1px;max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden; mso-hide: all; font-family: sans-serif;">
&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;
</div>
<div style="max-width: 600px; margin: 0 auto;" class="email-container">
<!-- BEGIN BODY -->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="logo" style="text-align: center;">
<h1>
<a href="#">
<img src="https://ci3.googleusercontent.com/proxy/x3ocY0ISnAVX5bLWQ_SFLMFkuW31hX5OPBfAfUqnEvtjgsI8O-4XtrVut9XyZE0KrbVtdS8Bj0dIhQ=s0-d-e1-ft#https://app.ira-lex.com/assets/logo.png"
alt=""
style="width: 100px; max-width: 600px; height: auto; margin: auto; display: block;">
</a>
</h1>
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 3em 0 2em 0;">
<img src="https://ci4.googleusercontent.com/proxy/UMF8BOFy2GQHbjvPAShH5Ian8v99R82HSxMPaVI5tyeGwMWS9LjetVHiAZDMw3gXHGSAQd3dnQrlX00=s0-d-e1-ft#https://app.ira-lex.com/assets/email.png"
alt="" style="width: 300px; max-width: 600px; height: auto; margin: auto; display: block;">
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
<table>
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<h2>You are nearly there!</h2>
<p id="fullName">
Hi {name}
</p>
<p>
kljvl
To finish setting up your account and start using IRALEX, confirm weve
got the correct email for you.
</p>
<p><a href="{verifyLink}" class="btn btn-primary"
style="background: #0000EE; color: #FFFFFF; border-radius: 10px; text-decoration: none; padding: 15px;">
dclkvkjlj</a></p>
</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<!-- 1 Column Text + Button : END -->
</table>
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="bg_light footer email-section">
<table>
<tr>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-right: 10px;">
<h3 class="heading">About</h3>
<p>IRALEX is a comprehensive legal practice management software designed to
help lawfirms handle day-to-day operations efficiently.</p>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 5px; padding-right: 5px;">
<h3 class="heading">Contact Info</h3>
<ul>
<li><span class="text"><a href="https://goo.gl/maps/d7KHzKSme9yZ16Ds9">2B-5-8, Block B, Plaza Mont Kiara, No. 2, Jalan Kiara, Mont Kiara, 50480 Kuala Lumpur, Malaysia</a></span>
</li>
<li><span class="text"><a
href="tel:+601128018817">+6011 2801 8817</a></span></li>
<li><span class="text"><a href="mailto:info@ira-lex.com">info@ira-lex.com</a></span>
</li>
</ul>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 10px;">
<h3 class="heading">Useful Links</h3>
<ul>
<li><a href="https://ira-lex.com/">Home</a></li>
<li><a href="https://ira-lex.com/aboutus">About</a></li>
<li><a href="https://ira-lex.com/app/register">Sign Up</a></li>
<li><a href="https://ira-lex.com/app/login">Login</a></li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- end: tr -->
<tr>
<td class="bg_light" style="text-align: center;">
</td>
</tr>
</table>
</div>
</center>
</body>
</html>

View File

@ -0,0 +1,137 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8">
<!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width">
<!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting">
<!-- Disable auto-scale in iOS 10 Mail entirely -->
<title>IRALEX email</title>
<!-- The title tag shows in email notifications, like Android 4.4. -->
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
</head>
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
<center style="width: 100%; background-color: #f1f1f1;">
<div style="max-width: 600px; margin: 0 auto;" class="email-container">
<!-- BEGIN BODY -->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="hero bg_white" style="padding: 3em 0 2em 0;">
<img src="https://ci3.googleusercontent.com/proxy/x3ocY0ISnAVX5bLWQ_SFLMFkuW31hX5OPBfAfUqnEvtjgsI8O-4XtrVut9XyZE0KrbVtdS8Bj0dIhQ=s0-d-e1-ft#https://app.ira-lex.com/assets/logo.png"
alt="" style="width: 100px; max-width: 600px; height: auto; margin: auto; display: block;">
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
<img alt=""
src="https://ira-lex.com/app/Reminders%20(1).png"
style="width: 300px; max-width: 600px; height: auto; margin: auto; display: block;"
/>
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
<table>
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<h2>You forget your password</h2>
<p id="fullName">
Hi {name}
</p>
<p style="margin-bottom: 30px">
We have received your request to reset your password in IraLex.Please click on
the following link to enter a new password.
</p>
<p><a href="{verifyLink}" class="btn btn-primary"
style="background: #0000EE; color: #FFFFFF; border-radius: 10px; text-decoration: none; padding: 15px;">
Set New Password</a></p>
</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<!-- 1 Column Text + Button : END -->
</table>
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="bg_light footer email-section">
<table>
<tr>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-right: 10px;">
<h3 class="heading">About</h3>
<p>IRALEX is a comprehensive legal practice management software designed to
help lawfirms handle day-to-day operations efficiently.</p>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 5px; padding-right: 5px;">
<h3 class="heading">Contact Info</h3>
<ul>
<li><span class="text"><a href="https://goo.gl/maps/d7KHzKSme9yZ16Ds9">2B-5-8, Block B, Plaza Mont Kiara, No. 2, Jalan Kiara, Mont Kiara, 50480 Kuala Lumpur, Malaysia</a></span>
</li>
<li><span class="text"><a
href="tel:+601128018817">+6011 2801 8817</a></span></li>
<li><span class="text"><a href="mailto:info@ira-lex.com">info@ira-lex.com</a></span>
</li>
</ul>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 10px;">
<h3 class="heading">Useful Links</h3>
<ul>
<li><a href="https://ira-lex.com/">Home</a></li>
<li><a href="https://ira-lex.com/aboutus">About</a></li>
<li><a href="https://ira-lex.com/app/register">Sign Up</a></li>
<li><a href="https://ira-lex.com/app/login">Login</a></li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- end: tr -->
<tr>
<td class="bg_light" style="text-align: center;">
</td>
</tr>
</table>
</div>
</center>
</body>
</html>

View File

@ -0,0 +1,135 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8">
<!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width">
<!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting">
<!-- Disable auto-scale in iOS 10 Mail entirely -->
<title>IRALEX email</title>
<!-- The title tag shows in email notifications, like Android 4.4. -->
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
</head>
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
<center style="width: 100%; background-color: #f1f1f1;">
<div style="max-width: 600px; margin: 0 auto;" class="email-container">
<!-- BEGIN BODY -->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="hero bg_white" style="padding: 3em 0 2em 0;">
<img src="https://ci3.googleusercontent.com/proxy/x3ocY0ISnAVX5bLWQ_SFLMFkuW31hX5OPBfAfUqnEvtjgsI8O-4XtrVut9XyZE0KrbVtdS8Bj0dIhQ=s0-d-e1-ft#https://app.ira-lex.com/assets/logo.png"
alt="" style="width: 100px; max-width: 600px; height: auto; margin: auto; display: block;">
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
<img src="https://ira-lex.com/app/Attached%20files-bro%20(1).png" alt="" style="width: 300px; max-width: 600px; height: auto; margin: auto; display: block;">
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
<table style="width: 100%">
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<h2>You are nearly there!</h2>
<p id="fullName">
Dear {responsible_lawyer}
</p>
<p style="margin-bottom: 40px">
A new document has been attached to {matter_name} matter by {creator_name}.
</p>
<p>
<p><a href="{main_url}/document?mater_id={matter_id}"
style="background: #0000EE; color: #FFFFFF; border-radius: 10px; text-decoration: none; padding: 15px;"
class="btn btn-primary">View Docs</a></p>
</a></p>
</div>
</td>
</tr>
</table
</td>
</tr>
<!-- end tr -->
<!-- 1 Column Text + Button : END -->
</table>
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="bg_light footer email-section">
<table>
<tr>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-right: 10px;">
<h3 class="heading">About</h3>
<p>IRALEX is a comprehensive legal practice management software designed to
help lawfirms handle day-to-day operations efficiently.</p>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 5px; padding-right: 5px;">
<h3 class="heading">Contact Info</h3>
<ul>
<li><span class="text"><a href="https://goo.gl/maps/d7KHzKSme9yZ16Ds9">2B-5-8, Block B, Plaza Mont Kiara, No. 2, Jalan Kiara, Mont Kiara, 50480 Kuala Lumpur, Malaysia</a></span>
</li>
<li><span class="text"><a
href="tel:+601128018817">+6011 2801 8817</a></span></li>
<li><span class="text"><a href="mailto:info@ira-lex.com">info@ira-lex.com</a></span>
</li>
</ul>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 10px;">
<h3 class="heading">Useful Links</h3>
<ul>
<li><a href="https://ira-lex.com/">Home</a></li>
<li><a href="https://ira-lex.com/aboutus">About</a></li>
<li><a href="https://ira-lex.com/app/register">Sign Up</a></li>
<li><a href="https://ira-lex.com/app/login">Login</a></li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- end: tr -->
<tr>
<td class="bg_light" style="text-align: center;">
</td>
</tr>
</table>
</div>
</center>
</body>
</html>

View File

@ -0,0 +1,158 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8">
<!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width">
<!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting">
<!-- Disable auto-scale in iOS 10 Mail entirely -->
<title>IRALEX email</title>
<!-- The title tag shows in email notifications, like Android 4.4. -->
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
</head>
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
<center style="width: 100%; background-color: #f1f1f1;">
<div style="max-width: 600px; margin: 0 auto;" class="email-container">
<!-- BEGIN BODY -->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td valign="middle" class="hero bg_white" style="padding: 3em 0 2em 0;">
<img src="https://ci3.googleusercontent.com/proxy/x3ocY0ISnAVX5bLWQ_SFLMFkuW31hX5OPBfAfUqnEvtjgsI8O-4XtrVut9XyZE0KrbVtdS8Bj0dIhQ=s0-d-e1-ft#https://app.ira-lex.com/assets/logo.png"
alt="" style="width: 100px; max-width: 600px; height: auto; margin: auto; display: block;">
</td>
</tr>
<tr>
<td class="logo" style="text-align: center;">
<h1>
<img src="https://ira-lex.com/app/Attached%20files-bro%20(1).png"
alt="" style="width: auto; height: auto; margin: auto; display: block;">
</h1>
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
<table style="width: 100%">
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<h2>You are nearly there!</h2>
<p id="fullName">
Dear {user_name}
<br>
<br>
{maker_name} invited you to an event.
<br>
<br>
</p>
<p style="margin-bottom: 40px">
Start date : {start_date} - End date : {end_date}
<br>
Attendees : {attend_names}
<br>
Calender : {maker_name}
</p>
<p>
<a href="{main_url}/calendar" class="btn btn-primary"
style="background: #0000EE; color: #FFFFFF; border-radius: 10px; text-decoration: none; padding: 15px;">
View Calender
</a>
</p>
</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<!-- 1 Column Text + Button : END -->
</table>
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="bg_light footer email-section">
<table>
<tr>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-right: 10px;">
<h3 class="heading">About</h3>
<p>IRALEX is a comprehensive legal practice management software designed to
help lawfirms handle day-to-day operations efficiently.</p>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 5px; padding-right: 5px;">
<h3 class="heading">Contact Info</h3>
<ul>
<li><span class="text"><a href="https://goo.gl/maps/d7KHzKSme9yZ16Ds9">2B-5-8, Block B, Plaza Mont Kiara, No. 2, Jalan Kiara, Mont Kiara, 50480 Kuala Lumpur, Malaysia</a></span>
</li>
<li><span class="text"><a
href="tel:+601128018817">+6011 2801 8817</a></span></li>
<li><span class="text"><a href="mailto:info@ira-lex.com">info@ira-lex.com</a></span>
</li>
</ul>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 10px;">
<h3 class="heading">Useful Links</h3>
<ul>
<li><a href="https://ira-lex.com/">Home</a></li>
<li><a href="https://ira-lex.com/aboutus">About</a></li>
<li><a href="https://ira-lex.com/app/register">Sign Up</a></li>
<li><a href="https://ira-lex.com/app/login">Login</a></li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- end: tr -->
<tr>
<td class="bg_light" style="text-align: center;">
</td>
</tr>
</table>
</div>
</center>
</body>
</html>

View File

@ -0,0 +1,146 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8">
<!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width">
<!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting">
<!-- Disable auto-scale in iOS 10 Mail entirely -->
<title>IRALEX email</title>
<!-- The title tag shows in email notifications, like Android 4.4. -->
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
</head>
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
<center style="width: 100%; background-color: #f1f1f1;">
<div style="max-width: 600px; margin: 0 auto;" class="email-container">
<!-- BEGIN BODY -->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td valign="middle" class="hero bg_white" style="padding: 3em 0 2em 0;">
<img src="https://ci3.googleusercontent.com/proxy/x3ocY0ISnAVX5bLWQ_SFLMFkuW31hX5OPBfAfUqnEvtjgsI8O-4XtrVut9XyZE0KrbVtdS8Bj0dIhQ=s0-d-e1-ft#https://app.ira-lex.com/assets/logo.png"
alt=""
style="width: 100px; max-width: 600px; height: auto; margin: auto; display: block;">
</td>
</tr>
<!-- end tr -->
<tr>
<td class="logo" style="text-align: center;">
<h1>
<img src="https://ira-lex.com/app/Attached%20files-bro%20(1).png" alt="" style="width: 300px; max-width: 600px; height: auto; margin: auto; display: block;">
</h1>
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
<table style="width: 100%">
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<h2>You are nearly there!</h2>
<p id="fullName">
Dear {contact_name}
</p>
<p style="margin-bottom: 40px">
Your {matter_title} mater was created by {creator_name},your
responsible lawyer is {responsible_lawyer}.
</p>
<p> Reference Code : <b>{ref_code}</b></p>
</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<!-- 1 Column Text + Button : END -->
</table>
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="bg_light footer email-section">
<table>
<tr>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0"
width="100%">
<tr>
<td style="text-align: left; padding-right: 10px;">
<h3 class="heading">About</h3>
<p>IRALEX is a comprehensive legal practice management software
designed to help lawfirms handle day-to-day operations
efficiently.</p>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0"
width="100%">
<tr>
<td style="text-align: left; padding-left: 5px; padding-right: 5px;">
<h3 class="heading">Contact Info</h3>
<ul>
<li><span class="text"><a
href="https://goo.gl/maps/d7KHzKSme9yZ16Ds9">2B-5-8, Block B, Plaza Mont Kiara, No. 2, Jalan Kiara, Mont Kiara, 50480 Kuala Lumpur, Malaysia</a></span>
</li>
<li><span class="text"><a href="tel:+601128018817">+6011 2801 8817</a></span>
</li>
<li><span class="text"><a href="mailto:info@ira-lex.com">info@ira-lex.com</a></span>
</li>
</ul>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0"
width="100%">
<tr>
<td style="text-align: left; padding-left: 10px;">
<h3 class="heading">Useful Links</h3>
<ul>
<li><a href="https://ira-lex.com/">Home</a></li>
<li><a href="https://ira-lex.com/aboutus">About</a></li>
<li><a href="https://ira-lex.com/app/register">Sign Up</a>
</li>
<li><a href="https://ira-lex.com/app/login">Login</a></li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- end: tr -->
<tr>
<td class="bg_light" style="text-align: center;">
</td>
</tr>
</table>
</div>
</center>
</body>
</html>

View File

@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8">
<!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width">
<!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting">
<!-- Disable auto-scale in iOS 10 Mail entirely -->
<title>IRALEX email</title>
<!-- The title tag shows in email notifications, like Android 4.4. -->
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
</head>
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
<center style="width: 100%; background-color: #f1f1f1;">
<div style="max-width: 600px; margin: 0 auto;" class="email-container">
<!-- BEGIN BODY -->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="hero bg_white" style="padding: 3em 0 2em 0;">
<img src="https://ci3.googleusercontent.com/proxy/x3ocY0ISnAVX5bLWQ_SFLMFkuW31hX5OPBfAfUqnEvtjgsI8O-4XtrVut9XyZE0KrbVtdS8Bj0dIhQ=s0-d-e1-ft#https://app.ira-lex.com/assets/logo.png"
alt="" style="width: 100px; max-width: 600px; height: auto; margin: auto; display: block;">
</td>
</tr>
<!-- end tr -->
<tr>
<td class="logo" style="text-align: center;">
<h1>
<img src="https://ira-lex.com/app/Attached%20files-bro%20(1).png"
alt="" style="width: auto; height: auto; margin: auto; display: block;">
</h1>
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
<table style="width: 100%">
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<p id="fullName">
Dear {responsible_lawyer}
</p>
<p style="margin-bottom: 40px">
{matter_name} matter has been assigned to you by {creator_name}.
</p>
<p>
<a style="background: #0000EE; color: #FFFFFF; border-radius: 10px; text-decoration: none; padding: 15px;"
class="btn btn-primary" href="{main_url}/matters?id={matter_id}">
View Matter
</a>
</p>
</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<!-- 1 Column Text + Button : END -->
</table>
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="bg_light footer email-section">
<table>
<tr>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-right: 10px;">
<h3 class="heading">About</h3>
<p>IRALEX is a comprehensive legal practice management software designed to
help lawfirms handle day-to-day operations efficiently.</p>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 5px; padding-right: 5px;">
<h3 class="heading">Contact Info</h3>
<ul>
<li><span class="text"><a href="https://goo.gl/maps/d7KHzKSme9yZ16Ds9">2B-5-8, Block B, Plaza Mont Kiara, No. 2, Jalan Kiara, Mont Kiara, 50480 Kuala Lumpur, Malaysia</a></span>
</li>
<li><span class="text"><a
href="tel:+601128018817">+6011 2801 8817</a></span></li>
<li><span class="text"><a href="mailto:info@ira-lex.com">info@ira-lex.com</a></span>
</li>
</ul>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 10px;">
<h3 class="heading">Useful Links</h3>
<ul>
<li><a href="https://ira-lex.com/">Home</a></li>
<li><a href="https://ira-lex.com/aboutus">About</a></li>
<li><a href="https://ira-lex.com/app/register">Sign Up</a></li>
<li><a href="https://ira-lex.com/app/login">Login</a></li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- end: tr -->
<tr>
<td class="bg_light" style="text-align: center;">
</td>
</tr>
</table>
</div>
</center>
</body>
</html>

View File

@ -0,0 +1,145 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8">
<!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width">
<!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting">
<!-- Disable auto-scale in iOS 10 Mail entirely -->
<title>IRALEX email</title>
<!-- The title tag shows in email notifications, like Android 4.4. -->
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
</head>
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
<center style="width: 100%; background-color: #f1f1f1;">
<div style="max-width: 600px; margin: 0 auto;" class="email-container">
<!-- BEGIN BODY -->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td valign="middle" class="hero bg_white" style="padding: 3em 0 2em 0;">
<img src="https://ci3.googleusercontent.com/proxy/x3ocY0ISnAVX5bLWQ_SFLMFkuW31hX5OPBfAfUqnEvtjgsI8O-4XtrVut9XyZE0KrbVtdS8Bj0dIhQ=s0-d-e1-ft#https://app.ira-lex.com/assets/logo.png"
alt="" style="width: 100px; max-width: 600px; height: auto; margin: auto; display: block;">
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 3em 0 2em 0;">
<img src="https://ira-lex.com/app/Attached%20files-bro%20(1).png"
alt="" style="width: auto; max-width: 600px; height: auto; margin: auto; display: block;">
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
<table style="width: 100%">
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<p id="fullName">
Dear {invited_name}
</p>
<p style="margin-bottom: 40px">
You've been assigned to {task_name} by {inviter_name}.
</p>
<p>
<a style="background: #0000EE; color: #FFFFFF; border-radius: 10px; text-decoration: none; padding: 15px;"
href="{main_url}/task/list?task_id={task_id}">
View Task
</a>
</p>
</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<!-- 1 Column Text + Button : END -->
</table>
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="bg_light footer email-section">
<table>
<tr>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-right: 10px;">
<h3 class="heading">About</h3>
<p>IRALEX is a comprehensive legal practice management software designed to
help lawfirms handle day-to-day operations efficiently.</p>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 5px; padding-right: 5px;">
<h3 class="heading">Contact Info</h3>
<ul>
<li><span class="text"><a href="https://goo.gl/maps/d7KHzKSme9yZ16Ds9">2B-5-8, Block B, Plaza Mont Kiara, No. 2, Jalan Kiara, Mont Kiara, 50480 Kuala Lumpur, Malaysia</a></span>
</li>
<li><span class="text"><a
href="tel:+601128018817">+6011 2801 8817</a></span></li>
<li><span class="text"><a href="mailto:info@ira-lex.com">info@ira-lex.com</a></span>
</li>
</ul>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 10px;">
<h3 class="heading">Useful Links</h3>
<ul>
<li><a href="https://ira-lex.com/">Home</a></li>
<li><a href="https://ira-lex.com/aboutus">About</a></li>
<li><a href="https://ira-lex.com/app/register">Sign Up</a></li>
<li><a href="https://ira-lex.com/app/login">Login</a></li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- end: tr -->
<tr>
<td class="bg_light" style="text-align: center;">
</td>
</tr>
</table>
</div>
</center>
</body>
</html>

View File

@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8">
<!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width">
<!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting">
<!-- Disable auto-scale in iOS 10 Mail entirely -->
<title>IRALEX email</title>
<!-- The title tag shows in email notifications, like Android 4.4. -->
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
</head>
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
<center style="width: 100%; background-color: #f1f1f1;">
<div style="max-width: 600px; margin: 0 auto;" class="email-container">
<!-- BEGIN BODY -->
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="hero bg_white" style="padding: 3em 0 2em 0;">
<img src="https://ci3.googleusercontent.com/proxy/x3ocY0ISnAVX5bLWQ_SFLMFkuW31hX5OPBfAfUqnEvtjgsI8O-4XtrVut9XyZE0KrbVtdS8Bj0dIhQ=s0-d-e1-ft#https://app.ira-lex.com/assets/logo.png"
alt="" style="width: 100px; max-width: 600px; height: auto; margin: auto; display: block;">
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
<img src="https://ira-lex.com/app/fine%20(1).png" alt=""
style="width: auto; max-width: 600px; height: auto; margin: auto; display: block;">
</td>
</tr>
<!-- end tr -->
<tr>
<td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
<table style="width: 100%">
<tr>
<td>
<div class="text" style="padding: 0 2.5em; text-align: center;">
<p id="fullName">
Dear {lawyer_name}
</p>
<p style="margin-bottom: 40px">
Your {matter_name} has been reached to the budget limit.
</p>
<p>
<a style="background: #0000EE; color: #FFFFFF; border-radius: 10px; text-decoration: none; padding: 15px;"
href="{main_url}/matters?id={matter_id}">
View Matter
</a>
</p>
</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- end tr -->
<!-- 1 Column Text + Button : END -->
</table>
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
style="margin: auto;">
<tr>
<td valign="middle" class="bg_light footer email-section">
<table>
<tr>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-right: 10px;">
<h3 class="heading">About</h3>
<p>IRALEX is a comprehensive legal practice management software designed to
help lawfirms handle day-to-day operations efficiently.</p>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 5px; padding-right: 5px;">
<h3 class="heading">Contact Info</h3>
<ul>
<li><span class="text"><a href="https://goo.gl/maps/d7KHzKSme9yZ16Ds9">2B-5-8, Block B, Plaza Mont Kiara, No. 2, Jalan Kiara, Mont Kiara, 50480 Kuala Lumpur, Malaysia</a></span>
</li>
<li><span class="text"><a
href="tel:+601128018817">+6011 2801 8817</a></span></li>
<li><span class="text"><a href="mailto:info@ira-lex.com">info@ira-lex.com</a></span>
</li>
</ul>
</td>
</tr>
</table>
</td>
<td valign="top" width="33.333%" style="padding-top: 20px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="text-align: left; padding-left: 10px;">
<h3 class="heading">Useful Links</h3>
<ul>
<li><a href="https://ira-lex.com/">Home</a></li>
<li><a href="https://ira-lex.com/aboutus">About</a></li>
<li><a href="https://ira-lex.com/app/register">Sign Up</a></li>
<li><a href="https://ira-lex.com/app/login">Login</a></li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- end: tr -->
<tr>
<td class="bg_light" style="text-align: center;">
</td>
</tr>
</table>
</div>
</center>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More