first commit
This commit is contained in:
22
Dockerfile
Executable file
22
Dockerfile
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
FROM python:3.12-bullseye
|
||||||
|
|
||||||
|
ENV PYTHONFAULTHANDLER=1
|
||||||
|
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
ENV STRIPE_PUBLIC_KEY = pk_test_51OUbSMJznCGgUo9krwqaJkCtdnROJ2gyTcUWQGOHcaREDqP8dPGhMmLTbI1sFiyiKiK3BOPasTayBnFFth0pb81g00qlPdABbC
|
||||||
|
|
||||||
|
ENV STRIPE_SECRET_KEY = sk_test_51OUbSMJznCGgUo9kWM2Uv0UjM0Ai6etCOOHVKkgFBVxO66VtIqlOFL6lpWcEA7zgVFICrdQSjSRVQH58NRlYeIpC00T5Jvw9wQ
|
||||||
|
|
||||||
|
RUN mkdir -p /app
|
||||||
|
|
||||||
|
COPY requirements.txt /app
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN pip3 install -r requirements.txt
|
||||||
|
|
||||||
|
COPY . /app
|
||||||
|
|
||||||
|
CMD ["python", "app.py", "--host", "0.0.0.0"]
|
||||||
|
|
||||||
5
README.MD
Executable file
5
README.MD
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
# eamco
|
||||||
|
|
||||||
|
eamco is a site where you can ask questions and put bounties on it.
|
||||||
|
|
||||||
13
app.py
Executable file
13
app.py
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
from app import app
|
||||||
|
|
||||||
|
PORT = 4052
|
||||||
|
HOST = '0.0.0.0'
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(
|
||||||
|
debug=True,
|
||||||
|
host=HOST,
|
||||||
|
port=PORT,
|
||||||
|
use_reloader=True
|
||||||
|
)
|
||||||
186
app/__init__.py
Normal file
186
app/__init__.py
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
from flask import Flask, jsonify
|
||||||
|
from flask_bcrypt import Bcrypt
|
||||||
|
from flask_cors import CORS
|
||||||
|
from flask_marshmallow import Marshmallow
|
||||||
|
import os
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from flask_session import Session
|
||||||
|
from flask_login import LoginManager
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
from werkzeug.routing import BaseConverter
|
||||||
|
|
||||||
|
import stripe
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
from local_settings import ApplicationConfig
|
||||||
|
except Exception as e:
|
||||||
|
from settings import ApplicationConfig
|
||||||
|
|
||||||
|
|
||||||
|
app = Flask(__name__,
|
||||||
|
static_url_path='',
|
||||||
|
static_folder='static',
|
||||||
|
template_folder='templates')
|
||||||
|
|
||||||
|
|
||||||
|
app.config.from_object(ApplicationConfig)
|
||||||
|
|
||||||
|
session = sessionmaker()
|
||||||
|
|
||||||
|
check_enviroment = ApplicationConfig.CURRENT_SETTINGS
|
||||||
|
print(f"starting server with {check_enviroment} settings")
|
||||||
|
|
||||||
|
|
||||||
|
class RegexConverter(BaseConverter):
|
||||||
|
def __init__(self, url_map, *items):
|
||||||
|
super(RegexConverter, self).__init__(url_map)
|
||||||
|
self.regex = items[0]
|
||||||
|
|
||||||
|
|
||||||
|
app.url_map.converters['regex'] = RegexConverter
|
||||||
|
app.jinja_env.autoescape = True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# configure stripe
|
||||||
|
# stripe_keys = {
|
||||||
|
# 'secret_key': os.environ['STRIPE_SECRET_KEY'],
|
||||||
|
# 'publishable_key': os.environ['STRIPE_PUBLISHABLE_KEY'],
|
||||||
|
# }
|
||||||
|
|
||||||
|
stripe_keys = {
|
||||||
|
'secret_key': 'sk_test_51OUbSMJznCGgUo9kWM2Uv0UjM0Ai6etCOOHVKkgFBVxO66VtIqlOFL6lpWcEA7zgVFICrdQSjSRVQH58NRlYeIpC00T5Jvw9wQ',
|
||||||
|
'public_key': ' pk_test_51OUbSMJznCGgUo9krwqaJkCtdnROJ2gyTcUWQGOHcaREDqP8dPGhMmLTbI1sFiyiKiK3BOPasTayBnFFth0pb81g00qlPdABbC',
|
||||||
|
}
|
||||||
|
stripe.api_key = stripe_keys['secret_key']
|
||||||
|
|
||||||
|
app.config['SECRET_KEY'] = ApplicationConfig.SECRET_KEY
|
||||||
|
app.config['SESSION_TYPE'] = ApplicationConfig.SESSION_TYPE
|
||||||
|
app.config['SESSION_COOKIE_NAME'] = ApplicationConfig.SESSION_COOKIE_NAME
|
||||||
|
app.config['SESSION_COOKIE_SECURE'] = ApplicationConfig.SESSION_COOKIE_SECURE
|
||||||
|
app.config['SESSION_COOKIE_HTTPONLY'] = ApplicationConfig.SESSION_COOKIE_HTTPONLY
|
||||||
|
app.config['SESSION_COOKIE_SAMESITE'] = ApplicationConfig.SESSION_COOKIE_SAMESITE
|
||||||
|
app.config['SESSION_PERMANENT'] = ApplicationConfig.SESSION_PERMANENT
|
||||||
|
app.config['SESSION_USE_SIGNER'] = ApplicationConfig.SESSION_USE_SIGNER
|
||||||
|
app.config['SESSION_REDIS'] = ApplicationConfig.SESSION_REDIS
|
||||||
|
|
||||||
|
session.configure(bind=ApplicationConfig.SQLALCHEMY_DATABASE_URI)
|
||||||
|
db = SQLAlchemy(app)
|
||||||
|
bcrypt = Bcrypt(app)
|
||||||
|
server_session = Session(app)
|
||||||
|
ma = Marshmallow(app)
|
||||||
|
|
||||||
|
|
||||||
|
login_manager = LoginManager(app)
|
||||||
|
login_manager.session_protection = 'strong'
|
||||||
|
login_manager.anonymous_user = "Guest"
|
||||||
|
|
||||||
|
|
||||||
|
@login_manager.request_loader
|
||||||
|
def load_user_from_request(request):
|
||||||
|
from app.classes.auth import Auth_User
|
||||||
|
# first, try to log in using the api_key url arg
|
||||||
|
api_key = request.args.get('api_key')
|
||||||
|
if api_key:
|
||||||
|
user = db.session\
|
||||||
|
.query(Auth_User)\
|
||||||
|
.filter_by(api_key=api_key)\
|
||||||
|
.first()
|
||||||
|
if user:
|
||||||
|
return user
|
||||||
|
# next, try to log in using Basic Auth
|
||||||
|
api_key_auth = request.headers.get('Authorization')
|
||||||
|
if api_key_auth:
|
||||||
|
api_key = api_key_auth.replace('bearer ', '', 1)
|
||||||
|
if api_key.startswith('"') and api_key.endswith('"'):
|
||||||
|
api_key = api_key[1:-1]
|
||||||
|
user = db.session\
|
||||||
|
.query(Auth_User)\
|
||||||
|
.filter_by(api_key=api_key)\
|
||||||
|
.first()
|
||||||
|
if user:
|
||||||
|
return user
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
api_main = {
|
||||||
|
"origins": [ApplicationConfig.ORIGIN_URL],
|
||||||
|
"methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"],
|
||||||
|
"allow_headers": ['Authorization', 'application/json', 'authorization', 'Content-Type',
|
||||||
|
'Access-Control-Allow-Headers', 'Origin,Accept',
|
||||||
|
'X-Requested-With', 'Content-Type', 'Access-Control-Request-Method',
|
||||||
|
'Access-Control-Request-Headers']
|
||||||
|
}
|
||||||
|
cors = CORS(app, supports_credentials=True, resources={r'/*': api_main})
|
||||||
|
|
||||||
|
|
||||||
|
# bind a function after each request, even if an exception is encountered.
|
||||||
|
@app.teardown_request
|
||||||
|
def teardown_request(error):
|
||||||
|
db.session.remove()
|
||||||
|
|
||||||
|
|
||||||
|
@app.teardown_appcontext
|
||||||
|
def teardown_appcontext(error):
|
||||||
|
db.session.remove()
|
||||||
|
|
||||||
|
|
||||||
|
@app.errorhandler(500)
|
||||||
|
def internal_error500():
|
||||||
|
return jsonify({"error": "Internal Error 500"}), 500
|
||||||
|
|
||||||
|
|
||||||
|
@app.errorhandler(502)
|
||||||
|
def internal_error502():
|
||||||
|
return jsonify({"error": "Internal Error 502"}), 502
|
||||||
|
|
||||||
|
|
||||||
|
@app.errorhandler(404)
|
||||||
|
def internal_error404():
|
||||||
|
return jsonify({"error": "Internal Error 400"}), 400
|
||||||
|
|
||||||
|
|
||||||
|
@app.errorhandler(401)
|
||||||
|
def internal_error404():
|
||||||
|
return jsonify({"error": "Internal Error 401"}), 401
|
||||||
|
|
||||||
|
|
||||||
|
@app.errorhandler(400)
|
||||||
|
def internal_error400():
|
||||||
|
return jsonify({"error": "Internal Error 400"}), 400
|
||||||
|
|
||||||
|
|
||||||
|
@app.errorhandler(413)
|
||||||
|
def to_large_file():
|
||||||
|
return jsonify({"error": "File is too large. Use a smaller image/file."}), 413
|
||||||
|
|
||||||
|
|
||||||
|
@app.errorhandler(403)
|
||||||
|
def internal_error403():
|
||||||
|
return jsonify({"error": "Internal Error 403"}), 403
|
||||||
|
|
||||||
|
|
||||||
|
@app.errorhandler(405)
|
||||||
|
def internal_error():
|
||||||
|
return jsonify({"error": "Internal Error 405"}), 405
|
||||||
|
|
||||||
|
# link locations
|
||||||
|
from .main import main as main_blueprint
|
||||||
|
app.register_blueprint(main_blueprint, url_prefix='/main')
|
||||||
|
|
||||||
|
from .pay import pay as pay_blueprint
|
||||||
|
app.register_blueprint(pay_blueprint, url_prefix='/pay')
|
||||||
|
|
||||||
|
from .update import update as update_blueprint
|
||||||
|
app.register_blueprint(update_blueprint, url_prefix='/update')
|
||||||
|
|
||||||
|
from .auth import auth as auth_blueprint
|
||||||
|
app.register_blueprint(auth_blueprint, url_prefix='/auth')
|
||||||
|
|
||||||
|
|
||||||
|
with app.app_context():
|
||||||
|
db.configure_mappers()
|
||||||
|
db.create_all()
|
||||||
|
db.session.commit()
|
||||||
8
app/auth/__init__.py
Normal file
8
app/auth/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
|
||||||
|
auth = Blueprint('auth', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
from . import views
|
||||||
42
app/auth/views.py
Normal file
42
app/auth/views.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
from flask import request, jsonify
|
||||||
|
from app.auth import auth
|
||||||
|
from app import db
|
||||||
|
from app.classes.auth import Auth_User
|
||||||
|
|
||||||
|
|
||||||
|
@auth.route("/whoami", methods=["GET"])
|
||||||
|
def check_session():
|
||||||
|
"""
|
||||||
|
Checks auth token to ensure user is authenticated
|
||||||
|
"""
|
||||||
|
|
||||||
|
api_key = request.headers.get('Authorization')
|
||||||
|
if not api_key:
|
||||||
|
return jsonify({"error": "True"}), 200
|
||||||
|
else:
|
||||||
|
api_key = api_key.replace('bearer ', '', 1)
|
||||||
|
api_key = api_key.replace('"', '')
|
||||||
|
user_exists = db.session\
|
||||||
|
.query(Auth_User)\
|
||||||
|
.filter(Auth_User.api_key == api_key)\
|
||||||
|
.first()
|
||||||
|
if not user_exists:
|
||||||
|
return jsonify({"error": True}), 200
|
||||||
|
else:
|
||||||
|
user = db.session\
|
||||||
|
.query(Auth_User)\
|
||||||
|
.filter(Auth_User.api_key == api_key)\
|
||||||
|
.first()
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"ok": True,
|
||||||
|
'user': {
|
||||||
|
'user_name': user.display_name,
|
||||||
|
'user_email': user.email,
|
||||||
|
'user_admin': user.admin_role,
|
||||||
|
'token': user.api_key,
|
||||||
|
'confirmed': user.confirmed
|
||||||
|
},
|
||||||
|
'token': user.api_key
|
||||||
|
}), 200
|
||||||
|
|
||||||
0
app/classes/__init__.py
Normal file
0
app/classes/__init__.py
Normal file
79
app/classes/auth.py
Normal file
79
app/classes/auth.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
from flask_login import UserMixin, AnonymousUserMixin
|
||||||
|
from app import db, ma, login_manager
|
||||||
|
from datetime import datetime
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
|
|
||||||
|
def get_uuid():
|
||||||
|
return uuid4().hex
|
||||||
|
|
||||||
|
|
||||||
|
class Auth_User(UserMixin, db.Model):
|
||||||
|
__tablename__ = 'auth_users'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
autoincrement=True,
|
||||||
|
primary_key=True,
|
||||||
|
unique=True)
|
||||||
|
uuid = db.Column(db.String(32), default=get_uuid)
|
||||||
|
api_key = db.Column(db.TEXT)
|
||||||
|
username = db.Column(db.VARCHAR(40))
|
||||||
|
password_hash = db.Column(db.TEXT)
|
||||||
|
member_since = db.Column(db.TIMESTAMP(), default=datetime.utcnow())
|
||||||
|
email = db.Column(db.VARCHAR(350))
|
||||||
|
last_seen = db.Column(db.TIMESTAMP(), default=datetime.utcnow())
|
||||||
|
admin = db.Column(db.INTEGER)
|
||||||
|
admin_role = db.Column(db.INTEGER)
|
||||||
|
confirmed = db.Column(db.INTEGER)
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
username,
|
||||||
|
api_key,
|
||||||
|
password_hash,
|
||||||
|
member_since,
|
||||||
|
email,
|
||||||
|
last_seen,
|
||||||
|
admin,
|
||||||
|
admin_role,
|
||||||
|
confirmed,
|
||||||
|
):
|
||||||
|
self.username = username
|
||||||
|
self.api_key = api_key
|
||||||
|
self.password_hash = password_hash
|
||||||
|
self.member_since = member_since
|
||||||
|
self.email = email
|
||||||
|
self.last_seen = last_seen
|
||||||
|
self.admin = admin
|
||||||
|
self.admin_role = admin_role
|
||||||
|
self.confirmed = confirmed
|
||||||
|
|
||||||
|
def is_authenticated(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def is_active(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def is_anonymous(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
|
||||||
|
class Auth_User_Schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Auth_User
|
||||||
|
|
||||||
|
|
||||||
|
user_schema = Auth_User_Schema()
|
||||||
|
users_schema = Auth_User_Schema(many=True)
|
||||||
|
|
||||||
|
|
||||||
|
class AnonymousUser(AnonymousUserMixin):
|
||||||
|
def __init__(self):
|
||||||
|
self.username = 'Guest'
|
||||||
|
|
||||||
|
|
||||||
|
login_manager.anonymous_user = AnonymousUser
|
||||||
25
app/classes/company.py
Normal file
25
app/classes/company.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from app import db, ma
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Company_Company(db.Model):
|
||||||
|
__tablename__ = 'company_company'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
company_dba_name = db.Column(db.VARCHAR(250))
|
||||||
|
company_llc_name = db.Column(db.VARCHAR(250))
|
||||||
|
company_town = db.Column(db.VARCHAR(140))
|
||||||
|
company_state = db.Column(db.VARCHAR(140))
|
||||||
|
company_zip = db.Column(db.INTEGER)
|
||||||
|
|
||||||
|
|
||||||
|
class Company_Company_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Company_Company
|
||||||
|
|
||||||
81
app/classes/customer.py
Normal file
81
app/classes/customer.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
|
||||||
|
from app import db, ma, login_manager
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class Customer_Customer(db.Model):
|
||||||
|
__tablename__ = 'customer_customer'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
customer_last_name = db.Column(db.VARCHAR(250))
|
||||||
|
customer_first_name = db.Column(db.VARCHAR(250))
|
||||||
|
customer_town = db.Column(db.VARCHAR(140))
|
||||||
|
customer_state = db.Column(db.INTEGER)
|
||||||
|
customer_zip = db.Column(db.VARCHAR(25))
|
||||||
|
customer_first_call = db.Column(db.TIMESTAMP(), default=datetime.utcnow())
|
||||||
|
customer_email = db.Column(db.VARCHAR(500))
|
||||||
|
customer_automatic = db.Column(db.INTEGER)
|
||||||
|
customer_phone_number = db.Column(db.VARCHAR(25))
|
||||||
|
customer_home_type = db.Column(db.INTEGER)
|
||||||
|
customer_apt = db.Column(db.VARCHAR(140))
|
||||||
|
customer_address = db.Column(db.VARCHAR(1000))
|
||||||
|
|
||||||
|
|
||||||
|
class Customer_Customer_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Customer_Customer
|
||||||
|
|
||||||
|
|
||||||
|
class Customer_Property(db.Model):
|
||||||
|
__tablename__ = 'customer_property'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
customer_id = db.Column(db.INTEGER)
|
||||||
|
|
||||||
|
# residential = 0
|
||||||
|
# condo = 1
|
||||||
|
# apartment = 2
|
||||||
|
# commercial = 3
|
||||||
|
# business = 4
|
||||||
|
# vehicle = 4
|
||||||
|
customer_property_type = db.Column(db.INTEGER)
|
||||||
|
|
||||||
|
|
||||||
|
class Customer_Property_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Customer_Property
|
||||||
|
|
||||||
|
|
||||||
|
class Customer_Payment_Credit(db.Model):
|
||||||
|
__tablename__ = 'customer_payment'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
customer_id = db.Column(db.INTEGER)
|
||||||
|
|
||||||
|
credit_card_type = db.Column(db.INTEGER)
|
||||||
|
credit_card_name = db.Column(db.VARCHAR(240))
|
||||||
|
credit_card_number = db.Column(db.VARCHAR(140))
|
||||||
|
credit_card_security = db.Column(db.VARCHAR(140))
|
||||||
|
customer_card_expiration = db.Column(db.TIMESTAMP(), default=datetime.utcnow())
|
||||||
|
|
||||||
|
|
||||||
|
class Customer_Payment_Credit_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Customer_Payment_Credit
|
||||||
113
app/classes/delivery.py
Normal file
113
app/classes/delivery.py
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
from app import db, ma, login_manager
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class Delivery_Delivery(db.Model):
|
||||||
|
__tablename__ = 'delivery_delivery'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
customer_id = db.Column(db.INTEGER)
|
||||||
|
customer_name = db.Column(db.VARCHAR(1000))
|
||||||
|
customer_address = db.Column(db.VARCHAR(1000))
|
||||||
|
customer_town = db.Column(db.VARCHAR(140))
|
||||||
|
customer_state = db.Column(db.VARCHAR(140))
|
||||||
|
customer_zip = db.Column(db.INTEGER)
|
||||||
|
# how many gallons ordered
|
||||||
|
gallons_ordered = db.Column(db.INTEGER)
|
||||||
|
# if customer asked for a fill
|
||||||
|
customer_asked_for_fill = db.Column(db.INTEGER)
|
||||||
|
# integer value if delivered, waiting, cancelled etc
|
||||||
|
gallons_delivered = db.Column(db.INTEGER)
|
||||||
|
# if customer has a full tank
|
||||||
|
customer_filled = db.Column(db.INTEGER)
|
||||||
|
|
||||||
|
# integer value if delivered, waiting, cancelled etc
|
||||||
|
# waiting = 0
|
||||||
|
# delivered = 1
|
||||||
|
# out for delivery = 2
|
||||||
|
# cancelled = 3
|
||||||
|
# partial delivery = 4
|
||||||
|
delivery_status = db.Column(db.INTEGER)
|
||||||
|
|
||||||
|
# when the call to order took place
|
||||||
|
when_ordered = db.Column(db.TIMESTAMP(), default=datetime.utcnow())
|
||||||
|
# when the delivery date happened
|
||||||
|
when_delivered = db.Column(db.TIMESTAMP(), default=None)
|
||||||
|
# when the delivery is expected ie what day
|
||||||
|
expected_delivery_date = db.Column(db.DATE(), default=None)
|
||||||
|
# automatic delivery
|
||||||
|
automatic = db.Column(db.INTEGER)
|
||||||
|
|
||||||
|
# OIL info and id from table
|
||||||
|
oil_id = db.Column(db.INTEGER)
|
||||||
|
supplier_price = db.Column(db.DECIMAL(50, 2))
|
||||||
|
customer_price = db.Column(db.DECIMAL(50, 2))
|
||||||
|
|
||||||
|
# weather
|
||||||
|
customer_temperature = db.Column(db.DECIMAL(50, 2))
|
||||||
|
|
||||||
|
# services
|
||||||
|
dispatcher_notes = db.Column(db.TEXT())
|
||||||
|
prime = db.Column(db.INTEGER)
|
||||||
|
same_day = db.Column(db.INTEGER)
|
||||||
|
|
||||||
|
# cash = 0
|
||||||
|
# credit = 0
|
||||||
|
payment_type = db.Column(db.INTEGER)
|
||||||
|
|
||||||
|
|
||||||
|
class Delivery_Delivery_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Delivery_Delivery
|
||||||
|
|
||||||
|
|
||||||
|
class Delivery_Payment(db.Model):
|
||||||
|
__tablename__ = 'delivery_payment'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
delivery_id = db.Column(db.INTEGER)
|
||||||
|
time_added = db.Column(db.TIMESTAMP(), default=datetime.utcnow())
|
||||||
|
total_amount_oil = db.Column(db.DECIMAL(50, 2))
|
||||||
|
total_amount_emergency = db.Column(db.DECIMAL(50, 2))
|
||||||
|
total_amount_prime = db.Column(db.DECIMAL(50, 2))
|
||||||
|
total_amount_fee = db.Column(db.DECIMAL(50, 2))
|
||||||
|
total_amount = db.Column(db.DECIMAL(50, 2))
|
||||||
|
|
||||||
|
|
||||||
|
class Delivery_Payment_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Delivery_Payment
|
||||||
|
|
||||||
|
|
||||||
|
class Delivery_Notes_Driver(db.Model):
|
||||||
|
__tablename__ = 'delivery_notes'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
delivery_id = db.Column(db.INTEGER)
|
||||||
|
driver_comments = db.Column(db.TEXT)
|
||||||
|
time_added = db.Column(db.TIMESTAMP(), default=datetime.utcnow())
|
||||||
|
driver_id = db.Column(db.INTEGER)
|
||||||
|
driver_name = db.Column(db.VARCHAR(140))
|
||||||
|
|
||||||
|
|
||||||
|
class Delivery_Notes_Driver_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Delivery_Notes_Driver
|
||||||
73
app/classes/employee.py
Normal file
73
app/classes/employee.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
from app import db, ma
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class Employee_Employee(db.Model):
|
||||||
|
__tablename__ = 'employee_employee'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
user_id = db.Column(db.INTEGER)
|
||||||
|
employee_first_name = db.Column(db.VARCHAR(250))
|
||||||
|
employee_last_name = db.Column(db.VARCHAR(250))
|
||||||
|
employee_apt = db.Column(db.VARCHAR(250))
|
||||||
|
employee_address = db.Column(db.VARCHAR(1000))
|
||||||
|
employee_town = db.Column(db.VARCHAR(140))
|
||||||
|
employee_state = db.Column(db.VARCHAR(140))
|
||||||
|
employee_zip = db.Column(db.VARCHAR(25))
|
||||||
|
employee_birthday = db.Column(db.DATE(), default=datetime.utcnow())
|
||||||
|
employee_type = db.Column(db.INTEGER)
|
||||||
|
employee_phone_number = db.Column(db.VARCHAR(25))
|
||||||
|
employee_start_date = db.Column(db.DATE(), default=datetime.utcnow())
|
||||||
|
employee_end_date = db.Column(db.DATE(), default=None)
|
||||||
|
|
||||||
|
|
||||||
|
class Employee_Employee_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Employee_Employee
|
||||||
|
|
||||||
|
|
||||||
|
class Employee_Credentials(db.Model):
|
||||||
|
__tablename__ = 'employee_credentials'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
employee_id = db.Column(db.INTEGER)
|
||||||
|
employee_name = db.Column(db.VARCHAR(140))
|
||||||
|
employee_cdl_expire = db.Column(db.TIMESTAMP(), default=datetime.utcnow())
|
||||||
|
employee_hvac_expire = db.Column(db.TIMESTAMP(), default=datetime.utcnow())
|
||||||
|
|
||||||
|
|
||||||
|
class Employee_Credentials_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Employee_Credentials
|
||||||
|
|
||||||
|
|
||||||
|
class Employee_Vacation(db.Model):
|
||||||
|
__tablename__ = 'employee_vacation'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
employee_id = db.Column(db.INTEGER)
|
||||||
|
employee_name = db.Column(db.VARCHAR(140))
|
||||||
|
employee_total_days_off = db.Column(db.INTEGER)
|
||||||
|
employee_days_off_multiplier = db.Column(db.DECIMAL(50, 2))
|
||||||
|
employee_days_off_per_year = db.Column(db.INTEGER)
|
||||||
|
|
||||||
|
|
||||||
|
class Employee_Vacation_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Employee_Vacation
|
||||||
25
app/classes/oil.py
Normal file
25
app/classes/oil.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
from app import db, ma, login_manager
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Oil_Oil(db.Model):
|
||||||
|
__tablename__ = 'oil_oil'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
price_from_supplier = db.Column(db.DECIMAL(50, 2))
|
||||||
|
price_for_customer = db.Column(db.DECIMAL(50, 2))
|
||||||
|
price_for_employee = db.Column(db.DECIMAL(50, 2))
|
||||||
|
date = db.Column(db.TIMESTAMP(), default=datetime.utcnow())
|
||||||
|
|
||||||
|
class Oil_Oil_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Oil_Oil
|
||||||
|
|
||||||
70
app/classes/query.py
Normal file
70
app/classes/query.py
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
|
||||||
|
from app import db, ma
|
||||||
|
|
||||||
|
|
||||||
|
class Query_EmployeeTypeList(db.Model):
|
||||||
|
__tablename__ = 'query_employee_type_list'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
|
value = db.Column(db.INTEGER)
|
||||||
|
text = db.Column(db.VARCHAR(140))
|
||||||
|
|
||||||
|
|
||||||
|
class Query_EmployeeTypeList_Schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Query_EmployeeTypeList
|
||||||
|
id = ma.auto_field()
|
||||||
|
text = ma.auto_field()
|
||||||
|
value = ma.auto_field()
|
||||||
|
|
||||||
|
class Query_StateList(db.Model):
|
||||||
|
__tablename__ = 'query_state_list'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
|
value = db.Column(db.INTEGER)
|
||||||
|
text = db.Column(db.VARCHAR(140))
|
||||||
|
|
||||||
|
|
||||||
|
class Query_StateList_Schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Query_StateList
|
||||||
|
id = ma.auto_field()
|
||||||
|
text = ma.auto_field()
|
||||||
|
value = ma.auto_field()
|
||||||
|
|
||||||
|
|
||||||
|
class Query_CustomerTypeList(db.Model):
|
||||||
|
__tablename__ = 'query_customer_type_list'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
|
value = db.Column(db.INTEGER)
|
||||||
|
text = db.Column(db.VARCHAR(140))
|
||||||
|
|
||||||
|
|
||||||
|
class Query_CustomerTypeList_Schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Query_CustomerTypeList
|
||||||
|
id = ma.auto_field()
|
||||||
|
text = ma.auto_field()
|
||||||
|
value = ma.auto_field()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Query_ServiceTypeList(db.Model):
|
||||||
|
__tablename__ = 'query_service_type_list'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
|
value = db.Column(db.INTEGER)
|
||||||
|
text = db.Column(db.VARCHAR(140))
|
||||||
|
|
||||||
|
|
||||||
|
class Query_ServiceTypeList_Schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Query_ServiceTypeList
|
||||||
|
id = ma.auto_field()
|
||||||
|
text = ma.auto_field()
|
||||||
|
value = ma.auto_field()
|
||||||
127
app/classes/service.py
Normal file
127
app/classes/service.py
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
|
||||||
|
from app import db, ma
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Service_Call(db.Model):
|
||||||
|
__tablename__ = 'service_call'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
customer_id = db.Column(db.INTEGER)
|
||||||
|
customer_last_name = db.Column(db.VARCHAR(250))
|
||||||
|
customer_first_name = db.Column(db.VARCHAR(250))
|
||||||
|
customer_town = db.Column(db.VARCHAR(140))
|
||||||
|
customer_state = db.Column(db.INTEGER)
|
||||||
|
customer_zip = db.Column(db.VARCHAR(25))
|
||||||
|
customer_apt = db.Column(db.VARCHAR(140))
|
||||||
|
customer_address = db.Column(db.VARCHAR(1000))
|
||||||
|
|
||||||
|
#0 = closed
|
||||||
|
#1 = open
|
||||||
|
status = db.Column(db.INTEGER)
|
||||||
|
|
||||||
|
# 0 = unknown
|
||||||
|
# 1 = cleaning / tuneup
|
||||||
|
# 2 = problem
|
||||||
|
# 3 = install
|
||||||
|
# 3 = callback
|
||||||
|
service_type = db.Column(db.INTEGER)
|
||||||
|
|
||||||
|
# when the call to service took place
|
||||||
|
when_called = db.Column(db.DATE(), default=datetime.utcnow())
|
||||||
|
# what day the call will take place
|
||||||
|
scheduled_date = db.Column(db.DATE(), default=datetime.utcnow())
|
||||||
|
# what day the call will take place
|
||||||
|
scheduled_time = db.Column(db.INTEGER)
|
||||||
|
# when the service took place
|
||||||
|
when_serviced = db.Column(db.DATE(), default=datetime.utcnow())
|
||||||
|
|
||||||
|
# is the call finished or not
|
||||||
|
# 0 = open
|
||||||
|
#1 = finished
|
||||||
|
completed = db.Column(db.INTEGER)
|
||||||
|
tech_id = db.Column(db.INTEGER)
|
||||||
|
tech_first_name = db.Column(db.VARCHAR(300))
|
||||||
|
tech_last_name = db.Column(db.VARCHAR(300))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Service_Call_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Service_Call
|
||||||
|
|
||||||
|
|
||||||
|
class Service_Call_Money(db.Model):
|
||||||
|
__tablename__ = 'service_money'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
service_call_id = db.Column(db.INTEGER)
|
||||||
|
hours = db.Column(db.DECIMAL(50, 2))
|
||||||
|
cost_per_hour = db.Column(db.DECIMAL(50, 2))
|
||||||
|
parts_cost = db.Column(db.DECIMAL(50, 2))
|
||||||
|
total_cost_service = db.Column(db.DECIMAL(50, 2))
|
||||||
|
|
||||||
|
class Service_Call_Money_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Service_Call_Money
|
||||||
|
|
||||||
|
|
||||||
|
class Service_Call_Notes_Dispatcher(db.Model):
|
||||||
|
__tablename__ = 'service_notes_dispatcher'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
service_call_id = db.Column(db.INTEGER)
|
||||||
|
dispatcher_notes = db.Column(db.TEXT)
|
||||||
|
dispatcher_subject = db.Column(db.VARCHAR(1024))
|
||||||
|
time_added = db.Column(db.TIMESTAMP(), default=datetime.utcnow())
|
||||||
|
dispatcher_id = db.Column(db.INTEGER)
|
||||||
|
dispatcher_name = db.Column(db.VARCHAR(140))
|
||||||
|
|
||||||
|
|
||||||
|
class Service_Call_Notes_Dispatcher_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Service_Call_Notes_Dispatcher
|
||||||
|
|
||||||
|
|
||||||
|
class Service_Call_Notes_Technician(db.Model):
|
||||||
|
__tablename__ = 'service_notes_technician'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
service_call_id = db.Column(db.INTEGER)
|
||||||
|
technician_comments = db.Column(db.TEXT)
|
||||||
|
time_added = db.Column(db.TIMESTAMP(), default=datetime.utcnow())
|
||||||
|
technician_id = db.Column(db.INTEGER)
|
||||||
|
technician_name = db.Column(db.VARCHAR(140))
|
||||||
|
|
||||||
|
|
||||||
|
class Service_Call_Notes_Technician_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Service_Call_Notes_Technician
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
29
app/classes/stats_customer.py
Normal file
29
app/classes/stats_customer.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
from app import db, ma, login_manager
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class Stats_Customer(db.Model):
|
||||||
|
__tablename__ = 'stats_customer'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
total_calls = db.Column(db.INTEGER)
|
||||||
|
service_calls_total = db.Column(db.INTEGER)
|
||||||
|
service_calls_total_spent = db.Column(db.DECIMAL(50, 2))
|
||||||
|
service_calls_total_profit = db.Column(db.DECIMAL(50, 2))
|
||||||
|
|
||||||
|
|
||||||
|
oil_deliveries = db.Column(db.INTEGER)
|
||||||
|
oil_total_gallons = db.Column(db.INTEGER)
|
||||||
|
oil_total_spent = db.Column(db.DECIMAL(50, 2))
|
||||||
|
oil_total_profit = db.Column(db.DECIMAL(50, 2))
|
||||||
|
|
||||||
|
class Stats_Customer_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Stats_Customer
|
||||||
46
app/classes/stats_employee.py
Normal file
46
app/classes/stats_employee.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
from app import db, ma, login_manager
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class Stats_Employee_Oil(db.Model):
|
||||||
|
__tablename__ = 'stats_employee_oil'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
total_deliveries = db.Column(db.INTEGER)
|
||||||
|
total_gallons_delivered = db.Column(db.INTEGER)
|
||||||
|
total_primes = db.Column(db.INTEGER)
|
||||||
|
total_gallons_fuel = db.Column(db.INTEGER)
|
||||||
|
oil_total_profit_delivered = db.Column(db.DECIMAL(50, 2))
|
||||||
|
|
||||||
|
class Stats_Employee_Oil_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Stats_Employee_Oil
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Stats_Employee_Service(db.Model):
|
||||||
|
__tablename__ = 'stats_employee_service'
|
||||||
|
__bind_key__ = 'eamco'
|
||||||
|
__table_args__ = {"schema": "public"}
|
||||||
|
|
||||||
|
id = db.Column(db.Integer,
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
unique=False)
|
||||||
|
|
||||||
|
total_service_calls = db.Column(db.INTEGER)
|
||||||
|
total_service_calls_hours = db.Column(db.INTEGER)
|
||||||
|
total_gallons_fuel = db.Column(db.INTEGER)
|
||||||
|
total_amount_billed= db.Column(db.DECIMAL(50, 2))
|
||||||
|
total_profit_made = db.Column(db.DECIMAL(50, 2))
|
||||||
|
class Stats_Employee_Service_schema(ma.SQLAlchemyAutoSchema):
|
||||||
|
class Meta:
|
||||||
|
model = Stats_Employee_Service
|
||||||
0
app/common/__init__.py
Normal file
0
app/common/__init__.py
Normal file
15
app/common/decorators.py
Normal file
15
app/common/decorators.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from flask_login import current_user
|
||||||
|
from flask import abort
|
||||||
|
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
def login_required(f):
|
||||||
|
@wraps(f)
|
||||||
|
def decorated_function(*args, **kwargs):
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
abort(401)
|
||||||
|
return f(*args, **kwargs)
|
||||||
|
|
||||||
|
return decorated_function
|
||||||
0
app/create/__init__.py
Normal file
0
app/create/__init__.py
Normal file
41
app/create/views.py
Normal file
41
app/create/views.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
from flask import jsonify
|
||||||
|
import stripe
|
||||||
|
from app.create import create
|
||||||
|
|
||||||
|
|
||||||
|
@create.route("/create/product", methods=["GET"])
|
||||||
|
def create_product():
|
||||||
|
"""
|
||||||
|
Creates a product
|
||||||
|
"""
|
||||||
|
create_a_product = stripe.Product.create(
|
||||||
|
name="Oil",
|
||||||
|
active=True,
|
||||||
|
description="One Gallon of Oil",
|
||||||
|
shippable=False,
|
||||||
|
)
|
||||||
|
return jsonify({
|
||||||
|
"ok": True,
|
||||||
|
'info': create_a_product,
|
||||||
|
}), 200
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@create.route("/create/price", methods=["GET"])
|
||||||
|
def create_product_price():
|
||||||
|
"""
|
||||||
|
Sets the price of the product
|
||||||
|
"""
|
||||||
|
|
||||||
|
create_price = stripe.Price.create(
|
||||||
|
product_data={"name": "Oil"},
|
||||||
|
unit_amount=350,
|
||||||
|
currency="usd",
|
||||||
|
)
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"ok": True,
|
||||||
|
'info': create_price,
|
||||||
|
}), 200
|
||||||
|
|
||||||
7
app/info/__init__.py
Normal file
7
app/info/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
info = Blueprint('info', __name__)
|
||||||
|
|
||||||
|
from . import views
|
||||||
17
app/info/views.py
Normal file
17
app/info/views.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from flask import request, jsonify
|
||||||
|
import stripe
|
||||||
|
from flask_login import current_user, logout_user, login_user, login_required
|
||||||
|
from app.info import info
|
||||||
|
from app import db
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@info.route("/balance", methods=["GET"])
|
||||||
|
def get_balance():
|
||||||
|
charge = stripe.Balance.retrieve()
|
||||||
|
return jsonify({
|
||||||
|
"ok": True,
|
||||||
|
'info': {
|
||||||
|
'charge': charge,
|
||||||
|
},
|
||||||
|
}), 200
|
||||||
7
app/main/__init__.py
Normal file
7
app/main/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
main = Blueprint('main', __name__)
|
||||||
|
|
||||||
|
from . import views
|
||||||
31
app/main/views.py
Normal file
31
app/main/views.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
from flask import jsonify, Response
|
||||||
|
from app import app
|
||||||
|
from app import stripe_keys
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/robots.txt')
|
||||||
|
@app.route('/sitemap.xml')
|
||||||
|
def static_from_root():
|
||||||
|
def disallow(string): return 'Disallow: {0}'.format(string)
|
||||||
|
return Response("User-agent: *\n{0}\n".format("\n".join([
|
||||||
|
disallow('/bin/*'),
|
||||||
|
disallow('/admin'),
|
||||||
|
])))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/index', methods=['GET'])
|
||||||
|
@app.route('/', methods=['GET'])
|
||||||
|
def index():
|
||||||
|
return jsonify({"success": "Api is online"}), 200
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/key')
|
||||||
|
def get_publishable_key():
|
||||||
|
"""
|
||||||
|
Gets the key for the frontend
|
||||||
|
"""
|
||||||
|
stripe_config = {'publicKey': stripe_keys['public_key']}
|
||||||
|
|
||||||
|
return jsonify(stripe_config)
|
||||||
|
|
||||||
7
app/pay/__init__.py
Normal file
7
app/pay/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
pay = Blueprint('pay', __name__)
|
||||||
|
|
||||||
|
from . import views
|
||||||
63
app/pay/views.py
Normal file
63
app/pay/views.py
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
from flask import jsonify
|
||||||
|
import stripe
|
||||||
|
from app.pay import pay
|
||||||
|
from app import db
|
||||||
|
from app.classes.delivery import Delivery_Delivery
|
||||||
|
from app.classes.service import Service_Call_Money
|
||||||
|
|
||||||
|
|
||||||
|
@pay.route("/oil/<int:delivery_id>", methods=["GET"])
|
||||||
|
def create_charge_oil(delivery_id):
|
||||||
|
|
||||||
|
get_oil_delivery = db.session\
|
||||||
|
.query(Delivery_Delivery)\
|
||||||
|
.filter(Delivery_Delivery.id == delivery_id)\
|
||||||
|
.first()
|
||||||
|
|
||||||
|
if get_oil_delivery.customer_asked_for_fill == 1:
|
||||||
|
gallons = get_oil_delivery.gallons_ordered
|
||||||
|
else:
|
||||||
|
gallons = 250
|
||||||
|
|
||||||
|
checkout_session = stripe.checkout.Session.create(
|
||||||
|
success_url='http://localhost:5173/success',
|
||||||
|
cancel_url='http://localhost:5173/canceled',
|
||||||
|
payment_method_types=['card'],
|
||||||
|
mode='payment',
|
||||||
|
line_items=[
|
||||||
|
{
|
||||||
|
'price': 'price_1OXTkZJznCGgUo9kIoz37lwg',
|
||||||
|
'quantity': gallons,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
)
|
||||||
|
return jsonify({'sessionId': checkout_session['id']})
|
||||||
|
|
||||||
|
|
||||||
|
@pay.route("/service/<int:service_id>", methods=["GET"])
|
||||||
|
def create_charge_service(service_id):
|
||||||
|
|
||||||
|
get_service_call = db.session\
|
||||||
|
.query(Service_Call_Money)\
|
||||||
|
.filter(Service_Call_Money.service_call_id == service_id)\
|
||||||
|
.first()
|
||||||
|
|
||||||
|
amount_to_charge = round(float(get_service_call.total_cost_service) * 100)
|
||||||
|
|
||||||
|
## TODO try stripe.charge.create ???!
|
||||||
|
checkout_session = stripe.checkout.Session.create(
|
||||||
|
success_url='http://localhost:5173/success',
|
||||||
|
cancel_url='http://localhost:5173/canceled',
|
||||||
|
payment_method_types=['card'],
|
||||||
|
mode='payment',
|
||||||
|
line_items=[
|
||||||
|
{
|
||||||
|
'price': 'price_1OXTkZJznCGgUo9kIoz37lwg',
|
||||||
|
'quantity': amount_to_charge,
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
)
|
||||||
|
return jsonify({'sessionId': checkout_session['id']})
|
||||||
7
app/update/__init__.py
Normal file
7
app/update/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
|
||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
update = Blueprint('update', __name__)
|
||||||
|
|
||||||
|
from . import views
|
||||||
73
app/update/views.py
Normal file
73
app/update/views.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
from flask import jsonify
|
||||||
|
import stripe
|
||||||
|
from app.update import update
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@update.route('/oil')
|
||||||
|
def update_price_oil():
|
||||||
|
|
||||||
|
update_price_oil = stripe.Price.modify(
|
||||||
|
"price_1MoBy5LkdIwHu7ixZhnattbh",
|
||||||
|
unit_amount=350,
|
||||||
|
)
|
||||||
|
|
||||||
|
return jsonify({-
|
||||||
|
"ok": True,
|
||||||
|
'info': update_price_oil
|
||||||
|
}), 200
|
||||||
|
|
||||||
|
|
||||||
|
@update.route('/prime')
|
||||||
|
def update_price_prime():
|
||||||
|
|
||||||
|
update_price_prime = stripe.Price.modify(
|
||||||
|
"price_1MoBy5LkdIwHu7ixZhnattbh",
|
||||||
|
unit_amount=350,
|
||||||
|
)
|
||||||
|
|
||||||
|
return jsonify({-
|
||||||
|
"ok": True,
|
||||||
|
'info': update_price_prime
|
||||||
|
}), 200
|
||||||
|
|
||||||
|
|
||||||
|
@update.route('/emergency')
|
||||||
|
def update_price_emergency():
|
||||||
|
|
||||||
|
update_price_emergency = stripe.Price.modify(
|
||||||
|
"price_1MoBy5LkdIwHu7ixZhnattbh",
|
||||||
|
unit_amount=350,
|
||||||
|
)
|
||||||
|
|
||||||
|
return jsonify({-
|
||||||
|
"ok": True,
|
||||||
|
'info': update_price_emergency
|
||||||
|
}), 200
|
||||||
|
|
||||||
|
|
||||||
|
@update.route('/sameday')
|
||||||
|
def update_price_sameday():
|
||||||
|
|
||||||
|
update_price_sameday = stripe.Price.modify(
|
||||||
|
"price_1MoBy5LkdIwHu7ixZhnattbh",
|
||||||
|
unit_amount=350,
|
||||||
|
)
|
||||||
|
|
||||||
|
return jsonify({-
|
||||||
|
"ok": True,
|
||||||
|
'info': update_price_sameday
|
||||||
|
}), 200
|
||||||
|
|
||||||
|
|
||||||
|
@update.route('/service')
|
||||||
|
def update_price_service():
|
||||||
|
|
||||||
|
update_price_service = stripe.Price.modify(
|
||||||
|
"price_1MoBy5LkdIwHu7ixZhnattbh",
|
||||||
|
unit_amount=17500,
|
||||||
|
)
|
||||||
|
return jsonify({-
|
||||||
|
"ok": True,
|
||||||
|
'info': update_price_service
|
||||||
|
}), 200
|
||||||
64
local_settings.py
Executable file
64
local_settings.py
Executable file
@@ -0,0 +1,64 @@
|
|||||||
|
import redis
|
||||||
|
|
||||||
|
|
||||||
|
class ApplicationConfig:
|
||||||
|
"""
|
||||||
|
Basic Configuration for a generic User
|
||||||
|
"""
|
||||||
|
|
||||||
|
# configuration
|
||||||
|
STRIPE_PUBLIC_KEY = 'pk_test_51OUbSMJznCGgUo9krwqaJkCtdnROJ2gyTcUWQGOHcaREDqP8dPGhMmLTbI1sFiyiKiK3BOPasTayBnFFth0pb81g00qlPdABbC'
|
||||||
|
STRIPE_SECRET_KEY = 'sk_test_51OUbSMJznCGgUo9kWM2Uv0UjM0Ai6etCOOHVKkgFBVxO66VtIqlOFL6lpWcEA7zgVFICrdQSjSRVQH58NRlYeIpC00T5Jvw9wQ'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CURRENT_SETTINGS = 'LOCAL'
|
||||||
|
# databases info
|
||||||
|
POSTGRES_USERNAME = 'postgres'
|
||||||
|
POSTGRES_PW = 'postgres'
|
||||||
|
POSTGRES_SERVER = '172.19.0.1:5432'
|
||||||
|
POSTGRES_DBNAME00 = 'eamco'
|
||||||
|
SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{}:{}@{}/{}".format(POSTGRES_USERNAME,
|
||||||
|
POSTGRES_PW,
|
||||||
|
POSTGRES_SERVER,
|
||||||
|
POSTGRES_DBNAME00
|
||||||
|
)
|
||||||
|
SQLALCHEMY_BINDS = {'eamco': SQLALCHEMY_DATABASE_URI}
|
||||||
|
# sqlalchemy config
|
||||||
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||||
|
TRAP_HTTP_EXCEPTIONS = True
|
||||||
|
PROPAGATE_EXCEPTIONS = True
|
||||||
|
DEBUG = True
|
||||||
|
UPLOADED_FILES_DEST_ITEM = '/data/item'
|
||||||
|
|
||||||
|
# file uploads
|
||||||
|
UPLOADED_FILES_ALLOW = ['png', 'jpeg', 'jpg', 'png', 'gif']
|
||||||
|
MAX_CONTENT_LENGTH = 5 * 2500 * 2500
|
||||||
|
ALLOWED_EXTENSIONS = ['png', 'jpeg', 'jpg', 'png', 'gif']
|
||||||
|
|
||||||
|
# secret keys
|
||||||
|
SECRET_KEY = "youwillneverguessthiskeycia"
|
||||||
|
|
||||||
|
# sessions
|
||||||
|
SESSION_COOKIE_NAME = "quest_session"
|
||||||
|
SESSION_COOKIE_SECURE = False
|
||||||
|
SESSION_COOKIE_HTTPONLY = True
|
||||||
|
REMEMBER_COOKIE_HTTPONLY = True
|
||||||
|
SESSION_COOKIE_SAMESITE = "Strict"
|
||||||
|
SESSION_PERMANENT = False
|
||||||
|
SESSION_USE_SIGNER = True
|
||||||
|
|
||||||
|
# redis config
|
||||||
|
SESSION_TYPE = "redis"
|
||||||
|
SESSION_REDIS = redis.from_url("redis://redis:6379")
|
||||||
|
|
||||||
|
# CORS
|
||||||
|
ORIGIN_URL = "http://localhost:5173"
|
||||||
|
CORS_SEND_WILDCARD = False
|
||||||
|
CORS_SUPPORT_CREDENTIALS = True
|
||||||
|
CORS_EXPOSE_HEADERS = None
|
||||||
|
CORS_ALLOW_HEADERS = "*"
|
||||||
|
CORS_ORIGIN_WHITELIST = ['http://localhost', '*']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
22
requirements.txt
Executable file
22
requirements.txt
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
flask==2.3.3
|
||||||
|
flask_sqlalchemy
|
||||||
|
flask_session==0.5.0
|
||||||
|
flask-login==0.6.3
|
||||||
|
flask-moment
|
||||||
|
flask-paranoid
|
||||||
|
flask-bcrypt
|
||||||
|
flask-cors
|
||||||
|
flask_marshmallow
|
||||||
|
gunicorn
|
||||||
|
python-dateutil
|
||||||
|
python-dotenv
|
||||||
|
marshmallow-sqlalchemy
|
||||||
|
psycopg2-binary
|
||||||
|
redis
|
||||||
|
sqlalchemy
|
||||||
|
flask_wtf
|
||||||
|
flask_mail
|
||||||
|
Werkzeug==2.3.8
|
||||||
|
|
||||||
|
|
||||||
|
stripe
|
||||||
11
runProduction.py
Executable file
11
runProduction.py
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
from app import app
|
||||||
|
|
||||||
|
PORT = 6000
|
||||||
|
HOST = '0.0.0.0'
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(
|
||||||
|
host=HOST,
|
||||||
|
port=PORT,
|
||||||
|
threaded=True
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user