Compare commits

...

15 Commits

Author SHA1 Message Date
Mustafa Yontar 73a5820535 docker compose run with .env file 4 years ago
Mustafa Yontar 24b5ebc40a Merge branch 'master' into autogenerate_flutter 4 years ago
Mustafa Yontar 739497f824 form generator , reference fields, list embeded fields , embeded fields created. 4 years ago
Mustafa Yontar 5994f2a155 generate flutter forms and models 4 years ago
Mustafa Yontar 539ff5e2e5 Merge pull request 'Update Docker Dev environment' (#9) from mrtmrcbr/Adunatio:updateDockerDevEnv into master 4 years ago
Mustafa Yontar 7e15e570db Merge pull request 'Fix typo at AuthMethots.py' (#11) from ooguz/Adunatio:master into master 4 years ago
Özcan Oğuz 5207e712bf
Fix typo at AuthMethods.py 4 years ago
Özcan Oğuz b57590b32f
Add .env to .gitignore 4 years ago
Mustafa Yontar ca49799d68 Merge pull request 'Update installation section' (#8) from mrtmrcbr/Adunatio:updateReadme into master 4 years ago
Mustafa Yontar 89aeb025f3 Merge pull request 'Configuration support via .env file' (#10) from ooguz/Adunatio:master into master 4 years ago
Özcan Oğuz 75d04c4268 Merge branch 'master' into master 4 years ago
Özcan Oğuz 1e90dec29e
Add configuration via .env file 4 years ago
murat emir cabaroğlu a1a11b2dd4 update mongo data mount point to volume 4 years ago
murat emir cabaroğlu 62c82d933c remove copy command in development dockerfile 4 years ago
murat emir cabaroğlu 74fcc75ee9 update instalation steps and add basic usage of this project 4 years ago
  1. 8
      .env.example
  2. 2
      .gitignore
  3. 2
      Dockerfile
  4. 67
      README.md
  5. 38
      docker-compose-dev.yaml
  6. 0
      internal_lib/AuthMethods.py
  7. 3
      internal_lib/EncryptedField.py
  8. 41
      main.py
  9. 15
      models/Account.py
  10. 38
      models/Group.py
  11. 27
      models/Payment.py
  12. 7
      models/Union.py
  13. 4
      models/User.py
  14. 1
      requirements.txt
  15. 0
      scripts/__init__.py
  16. 331
      scripts/generate_flutter_forms.py
  17. 212
      scripts/generate_flutter_model.py

@ -0,0 +1,8 @@
APP_SECRET=s3cr3tk3yh3r3
FLASK_DEBUG=1
MONGO_HOST=mongo
MONGO_USER=username
MONGO_PASSWORD=Pa$$w0rD
ADUNATIO_PRIV_KEY=privkey.pem

2
.gitignore vendored

@ -25,3 +25,5 @@ var/
trash
mongo_data_dir/*
.directory
.env
flutter_out/

@ -15,5 +15,5 @@ RUN apt-get update && apt-get install -y \
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run","--debugger"]

@ -2,20 +2,73 @@
Association software by [Özgür Yazılım Derneği](https://oyd.org.tr)
### Dev install
## Dev install
```bash
# clone the repository and get submodules
git clone https://git.oyd.org.tr/oyd/Adunatio.git
git clone --recurse-submodules git@git.oyd.org.tr:oyd/Adunatio.git Adunatio
# Go to project directory
cd Adunatio
git submodule init
git submodule update
docker-compose -f docker-compose-dev.yaml up
# Create a encrytion key
ssh-keygen -t rsa -b 4096 -f ./privkey.pem
# Run all system with docker
docker-compose -f docker-compose-dev.yaml up --build -d
```
You can access Adunatio from <http://localhost:5000/admin>
## How to use
- First, You must create a union from here <http://localhost:5000/admin/union/>
- Check your union password in logs. With this command, you should see this kind of line in logs
```sh
docker-compose -f docker-compose-dev.yaml logs web
...
...
[2021-02-04 20:39:16,685] INFO in Union: New union password : <PASSWORD>
...
```
You can access Adunatio from <http://localhost:5000>
- login with your union and get your Berear token. Your username is combination of your `Legal Registration Number` and `@root`
```sh
# Example Request with curl
curl --request POST \
--url http://localhost:5000/auth/login \
--header 'Content-Type: application/json' \
--data '{
"username":"<Legal Registration Number>@root",
"password":"<PASSWORD>"
}'
# Response
{
"access_token": "<Your Access Token>",
"status": true
}
```
- Test avaliable endpoints with your Berear token. Note that, header title must be `Adunation_Session_Token`
```sh
export ACCESS="<Your Access Token>"
```
```sh
curl -H "Adunation_Session_Token: Bearer $ACCESS" http://localhost:5000/api/user/
```
```sh
curl -H "Adunation_Session_Token: Bearer $ACCESS" http://localhost:5000/api/union/
```
### License
## License
Copyright (C) 2021 Özgür Yazılım Derneği

@ -1,31 +1,33 @@
version: "3.3"
version: "3"
services:
mongo:
image: mongo
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: xcoder
MONGO_INITDB_ROOT_PASSWORD: 4dun4710
env_file:
.env
volumes:
- ./mongo_data_dir/:/data/db/
- mongo_data:/data/db/
mongo-express:
image: mongo-express
restart: always
ports:
- 8081:8081
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: xcoder
ME_CONFIG_MONGODB_ADMINPASSWORD: 4dun4710
ME_CONFIG_OPTIONS_EDITORTHEME: ambiance
ME_CONFIG_BASICAUTH_USERNAME: xcoder
ME_CONFIG_BASICAUTH_PASSWORD: 4dun4710
env_file:
.env
web:
build: .
ports:
- "5000:5000"
environment:
ADUNATIO_PRIV_KEY: /code/privkey.pem
FLASK_DEBUG: 1
- 5000:5000
env_file:
.env
volumes:
- .:/code
volumes:
mongo_data:
driver_opts:
device: /home/john/PycharmProjects/Adunatio/mongo_data_dir/
type: xfs
o: bind

@ -13,7 +13,10 @@ class EncryptedStringField(BaseField):
def __init__(self, **kwargs):
import os
priv_key = os.environ.get('ADUNATIO_PRIV_KEY')
try:
self.keyPair = RSA.importKey(open(priv_key).read())
except:
pass
super().__init__(**kwargs)

@ -2,22 +2,39 @@ from flask import Flask, request, jsonify
from flask_admin.contrib.mongoengine import ModelView
from flask_jwt_extended import JWTManager, create_access_token
from mongoengine import connect
from werkzeug.security import check_password_hash
from werkzeug.security import check_password_hash ,generate_password_hash
from internal_lib.AuthMethots import AuthJWT
from models.Account import Account
from models.Group import Group, PaymentGroup
from models.Payment import Payments
from os import environ, path
from dotenv import load_dotenv
from internal_lib.AuthMethods import AuthJWT
from models.Group import Group
from models.Union import Union
from models.User import User
from restapi import MongoApi
from flask_admin import Admin
"""
Load .env file and get variables
"""
base_path = path.abspath(path.dirname(__file__))
load_dotenv(path.join(base_path, '.env'))
MONGO_HOST = environ.get('MONGO_HOST')
MONGO_USER = environ.get('MONGO_USER')
MONGO_PASSWORD = environ.get('MONGO_PASSWORD')
"""
Mongodb connection string
"""
connect('adunatio', host='mongo', username="xcoder", password="4dun4710", authentication_source='admin')
connect('adunatio', host=MONGO_HOST, username=MONGO_USER, password=MONGO_PASSWORD, authentication_source='admin')
app = Flask(__name__)
app.secret_key = "secret_key+secret_key"
app.secret_key = environ.get('APP_SECRET')
app.config["JWT_TOKEN_LOCATION"] = "headers"
app.config["JWT_HEADER_NAME"] = "Adunation_Session_Token"
app.config["JWT_HEADER_TYPE"] = "Bearer"
@ -31,8 +48,12 @@ jwt = JWTManager(app)
flask mongorester register
"""
api = MongoApi(app, authentication_methods=[AuthJWT])
api.register_model(User, uri="/api/user")
api.register_model(Union, uri="/api/union")
api.register_model(User, uri="/api/user/")
api.register_model(Union, uri="/api/union/")
api.register_model(Group, uri="/api/group/")
api.register_model(PaymentGroup, uri="/api/payment_group/")
api.register_model(Account, uri="/api/accounts/")
api.register_model(Payments, uri="/api/payments/")
"""
flask admin register
@ -66,7 +87,13 @@ def login():
app.logger.error(e)
return jsonify({"message": "Bad username or password", "error": "Unauthorized", "status": False}), 401
if not check_password_hash(user.password,password):
app.logger.error(password)
app.logger.error(username)
app.logger.error(generate_password_hash(password))
app.logger.error(user.password)
app.logger.error(check_password_hash(pwhash=user.password,password=password))
if check_password_hash(pwhash=user.password,password=password) == False:
return jsonify({"message": "Bad username or password", "error": "Unauthorized", "status":False}), 401
# Identity can be any data that is json serializable

@ -1,9 +1,24 @@
from mongoengine import *
from models.Union import Union
from restapi import Methods
class Account(Document):
meta = {
'index_background': True,
'index_cls': False,
'auto_create_index': True,
'can_query': True,
'with_sub_docs': True,
'methods': [Methods.Get, Methods.List, Methods.Create],
"indexes": [
('bank'),
("-bank"),
("union"),
('union', 'bank', "deleted")
],
}
union = ReferenceField(Union)
bank = StringField()
number = StringField()

@ -1,22 +1,52 @@
from mongoengine import *
from models.Union import Union
from restapi import Methods
class Group(Document):
meta = {
'index_background': True,
'index_cls': False,
'auto_create_index': True,
'can_query': True,
'with_sub_docs': True,
'methods': [Methods.Get, Methods.List, Methods.Create],
"indexes": [
('name'),
("-name"),
("union","deleted"),
("union","deleted","name"),
],
}
union = ReferenceField(Union)
name = StringField()
rights = ListField(StringField())
name = StringField(required=True)
rights = ListField(StringField(), required=True)
deleted = BooleanField(default=False)
def __unicode__(self):
return "{} {}".format(self.union.name, self.name)
class PaymentGroup(Document):
meta = {
'index_background': True,
'index_cls': False,
'auto_create_index': True,
'can_query': True,
'with_sub_docs': True,
'methods': [Methods.Get, Methods.List, Methods.Create],
"indexes": [
('name'),
("-name"),
("union"),
('union','name',"deleted")
],
}
union = ReferenceField(Union)
name = StringField()
name = StringField(required=True)
deleted = BooleanField(default=False)
discount_percent = IntField()
discount_percent = IntField(required=True)
def __unicode__(self):
return "{} {}".format(self.union.name, self.name)

@ -4,26 +4,41 @@ from models.Account import Account
from models.File import File
from models.Union import Union
from models.User import User
from restapi import Methods
class Payments(Document):
meta = {
'index_background': True,
'index_cls': False,
'auto_create_index': True,
'can_query': True,
'with_sub_docs': True,
'methods': [Methods.Get, Methods.List, Methods.Create],
"indexes": [
("union","deleted"),
("union","deleted","account"),
('user',"union"),
('user',"union","deleted"),
('union', "user","income","deleted"),
('union', "user","deleted")
],
}
"""
all payments income and outcome together!
"""
union = ReferenceField(Union)
user = ReferenceField(User)
user = ReferenceField(User, required=True)
income = BooleanField(default=False)
date = DateTimeField()
regular = BooleanField(default=False)
regular_type = StringField(choices=('Weekly', 'Monthly', 'Yearly'))
price = DecimalField()
price = DecimalField(required=True)
deleted = BooleanField(default=False)
description = StringField()
reference_no = StringField()
file = ReferenceField(File)
account = ReferenceField(Account)
account = ReferenceField(Account, required=True)
due_date = DateTimeField()
is_paid = BooleanField(default=False)
is_paid = BooleanField(default=False, required=True)
is_donate = BooleanField(default=False)

@ -20,7 +20,7 @@ class Union(Document):
"indexes": [
('name'),
("-name"),
]
],
}
name = StringField(required=True)
logo = ImageField(thumbnail_size=(120, 120))
@ -55,7 +55,8 @@ class Union(Document):
user.union = self
from flask import current_app
password = ''.join(choices(ascii_letters + digits, k=10))
current_app.logger.info("New union password : {}".format(password))
user.password = generate_password_hash(password)
passhash = generate_password_hash(password,salt_length=20)
current_app.logger.info("New union password : '{}'".format(password))
user.password = passhash
# TODO: send password via mail or sms or nothing
user.save()

@ -29,7 +29,9 @@ class User(Document):
('union'),
('username', 'union'),
('accept_date')
]
],
"auto_generated": ['union','deleted','member_no']
}
deleted = BooleanField(default=False)
union = ReferenceField(Union)

@ -7,3 +7,4 @@ flask_views
flask_login
pillow
flask-admin
python-dotenv

@ -0,0 +1,331 @@
from random import randint, choice
from string import ascii_lowercase
from models.Account import Account
from models.Payment import Payments
from models.User import User
from scripts.generate_flutter_model import build_class
def mainBuilder(classlist):
blist = []
for cls in classlist:
data = build_class(cls, blist)
blist = blist + data[1]
clstypeList = [i.__class__.__name__ for i in blist]
configlistNames = []
for classItem in data[0]:
saveAction = ""
imports = "import 'package:flutter/material.dart';\n"
imports += "import 'package:flutter/services.dart';\n"
imports += "import 'package:dio/dio.dart';\n"
imports += "import 'package:horde/widgets/HorusBox.dart';\n"
imports += "import 'package:dropdown_search/dropdown_search.dart';\n"
imports += "import '../Models.dart';\n"
controller = ""
controllerInit = ""
controllerDispose = ""
textFields = ""
for field in classItem.get('fields'):
if field.get('name') == "id":
continue
if field.get('autogen'):
continue
controller += "\tTextEditingController _{};\n".format(field.get('name'))
controllerInit += "\t\t_{} = new TextEditingController();\n".format(field.get('name'))
controllerDispose += "\t\t_{}.dispose();\n".format(field.get('name'))
req = ""
if field.get('required'):
req = """
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
"""
if field.get("is_class"):
# imports += "import 'package:adunationfe/data/models/{}.dart';\n".format(field.get('class_name'))
if field.get('islist'):
if field.get('embeded') == False:
controller += "\t\tList<{classname}> item{name};\n".format(
classname=field.get('class_name'),
name=field.get('name'))
controllerInit += "\t\t\titem{name} = [];\n".format(name=field.get('name'))
saveAction += "\t\tnew{classname}.{name} = item{name};\n".format(name=field.get('name'),
classname=classItem.get(
'class'))
else:
imports += "import 'Form{}.dart';\n".format(
field.get('class_name'))
if field.get('class_name') not in configlistNames:
clsname = field.get('class_name')
configlistNames.append(field.get('class_name'))
else:
clsname = field.get('class_name') + ''.join(
[choice(ascii_lowercase) for i in range(randint(3, 6))])
while clsname in configlistNames:
clsname = field.get('class_name') + ''.join(
[choice(ascii_lowercase) for i in range(randint(3, 6))])
configlistNames.append(clsname)
saveAction += "\t\tnew{classname}.{name} = item{clist}List;\n".format(clist=clsname,
name=field.get(
'name'),
classname=classItem.get(
'class'))
controller += """
List<{originclass}> item{classname}List = [];
""".format(originclass=field.get("class_name"), classname=clsname)
textFields += """
Padding(padding: EdgeInsets.only(left:40,right: 40),
child: Column(
children: [
Text('{cname} list'),
Column(
children: List.generate(item{clsname}List.length, (index) {{
return HorusBox(
child:
Row(
children: [
Expanded(child: Text(item{clsname}List[index].name)),
GestureDetector(
onTap: () {{
item{clsname}List.removeAt(index);
setState(() {{
}});
}},
child: Icon(Icons.delete),
)
],
)
,
);
}}),
)
],
),
),
ElevatedButton(onPressed: ()
{{
_showMaterialDialog(SingleChildScrollView(child:Container(width:500,height:500,child:new Form{classname}(onSave: ({classname} item) {{
item{clsname}List.add(item);
Navigator.pop(context);
setState(() {{
}});
}}))),"Create {cname}");
}}, child: Text('Add {cname}')),
SizedBox(
height: 15,
),
""".format(classname=field.get('class_name'), cname=field.get('name'), clsname=clsname)
elif field.get("embeded") == False:
controller += "\t\t{classname} item{name};\n".format(classname=field.get('class_name'),
name=field.get('name'))
saveAction += "\t\tnew{classname}.{name} = item{name};\n".format(name=field.get('name'),
classname=classItem.get(
'class'))
controllerInit += "\t\t\titem{name} = {classname}();\n".format(
classname=field.get('class_name'),
name=field.get('name'))
controller += "\t\tList<{classname}> {cname}List = [];".format(
classname=field.get('class_name'), cname=field.get('name'))
controller += """
Future<List<{classname}>> getData{classname}(filter) async {{
print(filter);
var response = await Dio().get(
"${{apiurl}}/{cname}",
queryParameters: {{"{search}__contains": filter}},
);
List<{classname}> models = [];
response.data.forEach((element) {{
{classname} cn = {classname}();
cn.name = element['{search}'];
models.add(cn);
}});
return models;
}}
""".format(classname=field.get('class_name'), cname=field.get('name'),
search=field.get('search_field'))
textFields += """
DropdownSearch<{classname}>(
mode: Mode.BOTTOM_SHEET,
showSearchBox: true,
onFind: (String filter) => getData{classname}(filter),
items: [],
itemAsString: ({classname} u) => u.{search},
isFilteredOnline: true,
autoValidateMode: AutovalidateMode.onUserInteraction,
validator: ({classname} u) =>
u == null ? "field is required " : null,
hint: "{cname} in menu mode",
onChanged: ({classname} selected) {{
item{cname} = selected;
setState(() {{
}});
}}),
SizedBox(
height: 15,
),
""".format(classname=field.get('class_name'), cname=field.get('name'),
search=field.get('search_field'))
elif field.get("embeded"):
imports += "import 'Form{}.dart';\n".format(
field.get('class_name'))
saveAction += "\t\tif(!_key{classname}.currentState.build{classname}()) return false;\n".format(
classname=field.get('class_name'))
saveAction += "\t\tnew{cname}.{name} = _key{classname}.currentState.new{classname};\n".format(
classname=field.get('class_name'), name=field.get('name'), cname=classItem.get('class'))
textFields += "Form{classname}(key:_key{classname}),".format(classname=field.get('class_name'))
controller += "\tGlobalKey<Form{}State> _key{} = GlobalKey();\n".format(field.get('class_name'),
field.get('class_name'))
elif field.get('choices'):
saveAction += "\t\tnew{classname}.{name} = _{name}.text;\n".format(name=field.get('name'),
classname=classItem.get('class'))
imports += "import 'package:dropdown_search/dropdown_search.dart';\n"
textFields += """
DropdownSearch<String>(
mode: Mode.BOTTOM_SHEET,
showClearButton: true,
showSearchBox: true,
label: '{name}',
showSelectedItem: true,
items: ['{items}'],
hint: "country in menu mode",
onChanged: print,
selectedItem: "")
,
SizedBox(
height: 15,
),
""".format(items="','".join(field.get('choices')), name=field.get('name'))
elif field.get('type') == 'String':
saveAction += "\t\tnew{classname}.{name} = _{name}.text;\n".format(name=field.get('name'),
classname=classItem.get('class'))
textFields += """
new TextFormField(
decoration: new InputDecoration(labelText: "Enter your {name}"),
controller: _{name},
{req}
),
SizedBox(
height: 15,
),
""".format(name=field.get('name'), req=req)
elif field.get('type') == 'int':
saveAction += "\t\tnew{classname}.{name} = int.tryParse(_{name}.text);\n".format(
name=field.get('name'),
classname=classItem.get('class'))
textFields += """
new TextFormField(
decoration: new InputDecoration(labelText: "Enter your {name}"),
controller: _{name},
keyboardType: TextInputType.number,
inputFormatters: < TextInputFormatter > [
FilteringTextInputFormatter.digitsOnly
],
{req}
),
SizedBox(
height: 15,
),
""".format(name=field.get('name'), req=req)
# elif field.get('is_class'):
# print(field)
# # exit()
cls_text = """
{imports}
class Form{classname} extends StatefulWidget {{
final Function onSave;
const Form{classname}({{Key key, this.onSave}}) : super(key: key);
@override
Form{classname}State createState() => Form{classname}State();
}}
class Form{classname}State extends State<Form{classname}> {{
{controller}
var apiurl = "";
{classname} new{classname} = new {classname}();
bool build{classname}() {{
if (_{classname}.currentState.validate()) {{
{saveact}
widget.onSave(new{classname});
return true;
}}
return false;
}}
_showMaterialDialog(content, title) {{
showDialog(
context: context,
builder: (_) => new AlertDialog(
title: new Text(title),
content: content,
));
}}
final _{classname} = GlobalKey<FormState>();
@override
void initState() {{
{initdata}
super.initState();
}}
@override
void dispose() {{
{dispose}
super.dispose();
}}
@override
Widget build(BuildContext context) {{
return new Form(
key:_{classname},
child:new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
{textfield}
Row(
children: [
widget.onSave !=null ? ElevatedButton(
child: Text('Save'),
onPressed: () {{
build{classname}();
}},
): Center()
],
)
])
);
}}
}}
""".format(imports=imports, classname=classItem.get('class'), controller=controller,
initdata=controllerInit, dispose=controllerDispose, textfield=textFields, saveact=saveAction)
f = open("flutter_out/Form{}.dart".format(classItem.get('class')), "w+")
f.write(cls_text)
f.close()
import os
os.chdir('../')
print(os.getcwd())
mainBuilder([User, Payments, Account])
os.system("flutter format flutter_out/")

@ -0,0 +1,212 @@
import mongoengine
import os
from models.Account import Account
from models.Payment import Payments
from models.User import *
from mongoengine import fields
types = {
mongoengine.fields.StringField: "String",
IntField: 'int',
BooleanField: 'bool',
FloatField: 'Float',
DictField: 'Map<String,dynamic>'
}
def to_camel_case(snake_str):
components = snake_str.split('_')
# We capitalize the first letter of each component except the first one
# with the 'title' method and join them together.
return components[0] + ''.join(x.title() for x in components[1:])
def buildReferenceField(field_object, builded):
if isinstance(field_object, (ReferenceField, EmbeddedDocumentField)):
if field_object.document_type not in builded:
builded.append(field_object.document_type)
return build_class(field_object.document_type, builded)
return None, builded
else:
return None, builded
def buildFields(field_object):
type = ""
if isinstance(field_object, mongoengine.fields.LongField):
type = "long"
elif isinstance(field_object, EncryptedStringField):
type = "String"
elif isinstance(field_object, fields.ImageField):
type = "String"
elif isinstance(field_object, EncryptedStringField):
type = "String"
elif isinstance(field_object, StringField):
type = "String"
elif isinstance(field_object, ObjectIdField):
type = "String"
elif isinstance(field_object, DateTimeField):
type = "DateTime"
elif isinstance(field_object, IntField):
type = "int"
elif isinstance(field_object, BooleanField):
type = "bool"
elif isinstance(field_object, FloatField):
type = "double"
elif isinstance(field_object, DictField):
type = "Map<String,dynamic>"
elif isinstance(field_object, DynamicField):
type = "dynamic"
else:
type = "String"
return type
def build_class(mongoClass, builded):
if builded is None:
builded = []
mClass = mongoClass
builded.append(mClass)
rClass = mongoClass()
builded.append(rClass)
class_list = []
field_list = []
for field in rClass._fields_ordered:
field_object = getattr(mClass, field)
ignore_fields = mClass._meta.get('ignore_fields')
autogen_fields = mClass._meta.get('auto_generated')
if not ignore_fields:
ignore_fields = []
if not autogen_fields:
autogen_fields = []
if isinstance(field_object, (ReferenceField, EmbeddedDocumentField)):
_, builded = buildReferenceField(field_object, builded)
if _ is not None:
class_list = class_list + list(_)
pn = field_object.document_type()
if field not in ignore_fields:
field_list.append(
{"type": pn._class_name, "origin_name": field, "name": to_camel_case(field), "islist": False,
"is_class": True, "required":field_object.required, "class_name": pn._class_name, "autogen": field in autogen_fields})
elif isinstance(field_object, ListField):
if isinstance(field_object.field, (ReferenceField, EmbeddedDocumentField)):
_, builded = buildReferenceField(field_object.field, builded)
if _ is not None:
class_list = class_list + list(_)
pn = field_object.field.document_type()
if field not in ignore_fields:
field_list.append(
{"type": "List<{}>".format(pn._class_name), "origin_name": field, "name": to_camel_case(field),
"islist": True, "is_class": True, "required":field_object.required, "class_name": pn._class_name, "autogen": field in autogen_fields})
else:
type = buildFields(field_object.field)
if field not in ignore_fields:
field_list.append({"type": "List<{}>".format(type), "name": to_camel_case(field), "origin_name": field,
"islist": True, "originType": field_object.field, "required":field_object.required, "autogen": field in autogen_fields,"choices":field_object.field.choices})
else:
type = buildFields(field_object)
if field not in ignore_fields:
chc = None
req = False
if field_object is not None:
chc = field_object.choices
req = field_object.required
field_list.append(
{"type": "{}".format(type), "name": to_camel_case(field), "origin_name": field, "islist": False,
"originType": field_object, "autogen": field in autogen_fields,"choices":chc,"required":req})
class_list.append({'class': rClass._class_name, "fields": field_list})
return class_list, builded
f = None
def print(item):
if f:
f.writelines(str(item) + "\n")
def buildFunctionFromJson(fields):
print("\t void fromJson(data) {")
for i in fields:
if i.get('type') != "DateTime":
if not i.get('islist') and not i.get('is_class'):
print("\t\tthis.{} = data[\"{}\"];".format(i.get('name'), i.get("origin_name")))
elif i.get('islist') and not i.get('is_class'):
print("\t\tthis.{}=[];".format(i.get('name')));
print("\t\tdata[\"{}\"].forEach((element)".format(i.get("origin_name")))
print("\t\t{")
print("\t\t\tthis.{}.add(element);".format(i.get('name')))
print("\t\t}"
");")
elif not i.get('islist') and i.get('is_class'):
print("\t\tthis.{} = {}();".format(i.get('name'), i.get('class_name')))
print("\t\tthis.{}.fromJson(data[\"{}\"]);".format(i.get('name'), i.get('origin_name')))
else:
print("\t\tthis.{}=[];".format(i.get('name')));
print("\t\tdata[\"{}\"].forEach((element)".format(i.get("origin_name")))
print("\t\t{")
print("\t\t\t{cname} cls = {cname}();".format(cname=i.get('class_name')))
print("\t\t\tcls.fromJson(data[\"{}\"]);".format(i.get('origin_name')))
print("\t\t\tthis.{}.add(cls);".format(i.get('name')))
print("\t\t}"
");")
print("\t}")
def exportJson(fields):
print("\tMap<String,dynamic> toJson() {")
print("\t\tMap<String,dynamic> output = {};")
for i in fields:
if i.get('type') != "DateTime":
if not i.get('islist') and not i.get('is_class'):
print("\t\toutput[\"{}\"] = this.{};".format(i.get('origin_name'), i.get("name")))
elif i.get('islist') and not i.get('is_class'):
print("\t\toutput[\"{}\"] = [];".format(i.get('origin_name')))
print("\t\tthis.{}.forEach((element) => output[\"{}\"].add(element));".format(i.get('name'),i.get('origin_name')))
elif i.get('islist') and i.get('is_class'):
print("\t\toutput[\"{}\"] = [];".format(i.get('origin_name')))
print("\t\tthis.{}.forEach((element) => output[\"{}\"].add(element.toJson()));".format(i.get('name'),
i.get('origin_name')))
elif not i.get('islist') and i.get('is_class'):
print("\t\toutput[\"{}\"] = this.{}.toJson();".format(i.get('origin_name'),i.get('name')))
print("\t\treturn output;")
print("\t}")
def mainBuilder(classlist):
global f
blist = []
for cls in classlist:
data = build_class(cls,blist)
blist = blist + data[1]
for i in data[0]:
f = open('flutter_out/{}.dart'.format(i.get('class')),"w")
print("import 'package:scoped_model/scoped_model.dart';")
print("class {} extends Model ".format(i.get('class')))
print("{")
for field in i.get('fields'):
print("\t {} {};".format(field.get('type'), field.get('name')))
print("")
print("\t// Build Functions")
print("\t// ")
buildFunctionFromJson(i.get('fields'))
exportJson(i.get('fields'))
print("}")
if __name__ == '__main__':
import os
os.chdir('../')
print(os.getcwd())
mainBuilder([User, Payments, Account])
Loading…
Cancel
Save