first commit

This commit is contained in:
2024-02-28 16:08:07 -05:00
commit 7556d1a75c
32 changed files with 1309 additions and 0 deletions

22
Dockerfile Executable file
View 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
View 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
View 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
View 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
View 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
View 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
View File

79
app/classes/auth.py Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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

View 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
View File

15
app/common/decorators.py Normal file
View 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
View File

41
app/create/views.py Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
)