commit b71bbe2dc5ccf96ac7f18e1dd565f107feebf2ec Author: amnesia Date: Wed Feb 28 16:10:40 2024 -0500 first commit diff --git a/README.MD b/README.MD new file mode 100755 index 0000000..45375d0 --- /dev/null +++ b/README.MD @@ -0,0 +1,5 @@ + +# eamco + +eamco is a site where you can ask questions and put bounties on it. + diff --git a/app.py b/app.py new file mode 100755 index 0000000..38abb03 --- /dev/null +++ b/app.py @@ -0,0 +1,13 @@ +# coding=utf-8 +from app import app + +PORT = 4056 +HOST = '0.0.0.0' + +if __name__ == '__main__': + app.run( + debug=True, + host=HOST, + port=PORT, + use_reloader=True + ) diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..9f6f26c --- /dev/null +++ b/app/__init__.py @@ -0,0 +1,210 @@ +# coding=utf-8 +from flask import Flask, jsonify +from flask_bcrypt import Bcrypt +from flask_cors import CORS +from flask_marshmallow import Marshmallow + +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 +from flask_mail import Mail + +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 + + +# configuration +UPLOADED_FILES_DEST_ITEM = ApplicationConfig.UPLOADED_FILES_DEST_ITEM +UPLOADED_FILES_ALLOW = ApplicationConfig.UPLOADED_FILES_ALLOW +CURRENT_SETTINGS = ApplicationConfig.CURRENT_SETTINGS + +app.config['UPLOADED_FILES_DEST_ITEM'] = ApplicationConfig.UPLOADED_FILES_DEST_ITEM +app.config['UPLOADED_FILES_ALLOW'] = ApplicationConfig.UPLOADED_FILES_ALLOW +app.config['MAX_CONTENT_LENGTH'] = ApplicationConfig.MAX_CONTENT_LENGTH +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['ORIGIN_URL'] = ApplicationConfig.ORIGIN_URL +app.config['CURRENT_SETTINGS'] = ApplicationConfig.CURRENT_SETTINGS +app.config['SECRET_KEY'] = ApplicationConfig.SECRET_KEY + +session.configure(bind=ApplicationConfig.SQLALCHEMY_DATABASE_URI) +db = SQLAlchemy(app) +bcrypt = Bcrypt(app) +server_session = Session(app) +ma = Marshmallow(app) +mail = Mail(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 .admin import admin as admin_blueprint +app.register_blueprint(admin_blueprint, url_prefix='/admin') + +from .main import main as main_blueprint +app.register_blueprint(main_blueprint, url_prefix='/main') + +from .customer import customer as customer_blueprint +app.register_blueprint(customer_blueprint, url_prefix='/customer') + +from .service import service as service_blueprint +app.register_blueprint(service_blueprint, url_prefix='/service') + +from .delivery import delivery as delivery_blueprint +app.register_blueprint(delivery_blueprint, url_prefix='/delivery') + +from .delivery_data import delivery_data as delivery_data_blueprint +app.register_blueprint(delivery_data_blueprint, url_prefix='/deliverydata') + +from .search import search as search_blueprint +app.register_blueprint(search_blueprint, url_prefix='/search') + +from .reports import reports as reports_blueprint +app.register_blueprint(reports_blueprint, url_prefix='/report') + +from .query import query as query_blueprint +app.register_blueprint(query_blueprint, url_prefix='/query') + +from .payment import payment as payment_blueprint +app.register_blueprint(payment_blueprint, url_prefix='/payment') + +from .auth import auth as auth_blueprint +app.register_blueprint(auth_blueprint, url_prefix='/auth') + +from .employees import employees as employees_blueprint +app.register_blueprint(employees_blueprint, url_prefix='/employee') + +from .info import info as info_blueprint +app.register_blueprint(info_blueprint, url_prefix='/info') + +from .stats import stats as stats_blueprint +app.register_blueprint(stats_blueprint, url_prefix='/stats') + +with app.app_context(): + db.configure_mappers() + db.create_all() + db.session.commit() diff --git a/app/admin/__init__.py b/app/admin/__init__.py new file mode 100644 index 0000000..19ee150 --- /dev/null +++ b/app/admin/__init__.py @@ -0,0 +1,6 @@ +# coding=utf-8 +from flask import Blueprint + +admin = Blueprint('admin', __name__) + +from . import views \ No newline at end of file diff --git a/app/admin/views.py b/app/admin/views.py new file mode 100644 index 0000000..255f7d0 --- /dev/null +++ b/app/admin/views.py @@ -0,0 +1,92 @@ +from flask import request, jsonify +from flask_login import current_user, logout_user, login_user, login_required +from app.admin import admin +from app import db +from datetime import datetime +from app.classes.pricing import (Pricing_Service_General, + Pricing_Oil_Oil, + Pricing_Service_General_schema, + Pricing_Oil_Oil_schema) + + +@admin.route("/oil/create", methods=["POST"]) +def create_oil_price(): + """ + Changes the price for oil deliveries + """ + now = datetime.utcnow() + price_from_supplier = request.json["price_from_supplier"] + price_for_customer = request.json["price_for_customer"] + price_for_employee = request.json["price_for_employee"] + + new_admin_oil_price = Pricing_Oil_Oil( + price_from_supplier=price_from_supplier, + price_for_customer=price_for_customer, + price_for_employee=price_for_employee, + date=now, + ) + + db.session.add(new_admin_oil_price) + db.session.commit() + + return jsonify({ + "ok": True, + 'price': new_admin_oil_price.id, + }), 200 + + +@admin.route("/service/create", methods=["POST"]) +def create_service_price(): + """ + Changes general labor rates prices + """ + now = datetime.utcnow() + price_service_hour = request.json["price_service_hour"] + price_emergency_service_hourly_rate = request.json["price_emergency_service_hour"] + price_emergency_call = request.json["price_emergency_call"] + price_out_of_oil = request.json["price_out_of_oil"] + price_prime = request.json["price_prime"] + + price_service = Pricing_Service_General( + price_service_hour=price_service_hour, + price_out_of_oil=price_out_of_oil, + price_emergency_service_hour=price_emergency_service_hourly_rate, + price_prime=price_prime, + price_emergency_call=price_emergency_call, + date=now, + ) + + db.session.add(price_service) + db.session.commit() + + return jsonify({ + "ok": True, + 'price': price_service.id, + }), 200 + + +@admin.route("/service/get", methods=["GET"]) +def get_service_price(): + """ + gets service prices + """ + get_service_prices = (db.session + .query(Pricing_Service_General) + .order_by(Pricing_Service_General.date.desc()) + .first()) + + price_schema = Pricing_Service_General_schema(many=False) + return jsonify(price_schema.dump(get_service_prices)) + + +@admin.route("/oil/get", methods=["GET"]) +def get_oil_price(): + """ + gets oil prices + """ + get_oil_prices = (db.session + .query(Pricing_Oil_Oil) + .order_by(Pricing_Oil_Oil.date.desc()) + .first()) + price_schema = Pricing_Oil_Oil_schema(many=False) + return jsonify(price_schema.dump(get_oil_prices)) diff --git a/app/auth/__init__.py b/app/auth/__init__.py new file mode 100644 index 0000000..f0114b9 --- /dev/null +++ b/app/auth/__init__.py @@ -0,0 +1,6 @@ +# coding=utf-8 +from flask import Blueprint + +auth = Blueprint('auth', __name__) + +from . import views \ No newline at end of file diff --git a/app/auth/views.py b/app/auth/views.py new file mode 100644 index 0000000..8f84b41 --- /dev/null +++ b/app/auth/views.py @@ -0,0 +1,215 @@ +from flask import request, jsonify +from flask_login import current_user, logout_user, login_user, login_required +from app.auth import auth +from app import db, bcrypt +from datetime import datetime +from uuid import uuid4 +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.username, + 'user_id': user.id, + 'user_email': user.email, + 'user_admin': user.admin_role, + 'token': user.api_key, + 'confirmed': user.confirmed + }, + 'token': user.api_key + }), 200 + + +@auth.route("/amiconfirmed", methods=["GET"]) +@login_required +def check_confirmed(): + """ + Checks to see if user confirmed with email or key + """ + user = db.session\ + .query(Auth_User)\ + .filter(Auth_User.id == current_user.id)\ + .first() + if user.confirmed == 0: + confirmed = False + else: + confirmed = True + + return jsonify({"status": confirmed}), 200 + + +@auth.route("/logout", methods=["POST"]) +def logout(): + """ + Logs a user out of session on backend + """ + try: + logout_user() + return jsonify({'status': 'logged out'}), 200 + except Exception as e: + return jsonify({"error", 'error'}), 400 + + +@auth.route("/login", methods=["POST"]) +def login(): + """ + Main post function to a user + """ + + username = request.json["username"] + password = request.json["password"] + + user = db.session\ + .query(Auth_User)\ + .filter_by(username=username)\ + .first() is not None + if not user: + return jsonify({"error": True}), 200 + user = db.session\ + .query(Auth_User)\ + .filter_by(username=username)\ + .first() + if not bcrypt.check_password_hash(user.password_hash, password): + + current_fails = int(user.fails) + new_fails = current_fails + 1 + user.fails = new_fails + db.session.add(user) + db.session.commit() + + return jsonify({"error": True}), 200 + user.locked = 0 + user.fails = 0 + db.session.add(user) + db.session.commit() + + + return jsonify({ + "ok": True, + 'user': {'user_id': user.uuid, + 'user_id': user.id, + 'user_email': user.email, + 'admin_role': user.admin_role, + 'token': user.api_key + }, + 'token': user.api_key + }), 200 + +@auth.route("/register", methods=["POST"]) +def register_user(): + """ + Main post function to register a user + """ + now = datetime.utcnow() + + username = request.json["username"] + email = request.json["email"] + password = request.json["password"] + + part_one_code = uuid4().hex + part_two_code = uuid4().hex + part_three_code = uuid4().hex + key = part_one_code + part_two_code + part_three_code + + # check if email exists + user_exists_email = db.session\ + .query(Auth_User)\ + .filter_by(email=email)\ + .first() is not None + if user_exists_email: + return jsonify({"error": "Email already exists"}), 200 + + # check if username exists + user_exists_username = db.session\ + .query(Auth_User)\ + .filter_by(username=username)\ + .first() is not None + if user_exists_username: + return jsonify({"error": "User already exists"}), 200 + + # hash password for database + hashed_password = bcrypt.generate_password_hash(password).decode('utf-8') + + new_user = Auth_User( + username=username, + email=email, + password_hash=hashed_password, + member_since=now, + api_key=key, + last_seen=now, + admin=0, + admin_role=0, + confirmed=0, + ) + + db.session.add(new_user) + + # commit to database + db.session.commit() + + # log user in as active not sure if needed with frontend + #login_user(new_user) + # current_user.is_authenticated() + # current_user.is_active() + + return jsonify({ + "ok": True, + 'user': { + 'user_email': new_user.email, + 'admin_role': new_user.admin_role, + 'token': new_user.api_key, + 'confirmed': new_user.confirmed, + }, + 'token': new_user.api_key + }), 200 + + +@auth.route('/change-password', methods=['POST']) +@login_required +def change_password(): + + new_password = request.json["new_password"] + new_password_confirm = request.json["password_confirm"] + + user = db.session\ + .query(Auth_User) \ + .filter(Auth_User.id == current_user.id) \ + .first() + + if str(new_password) != str(new_password_confirm): + return jsonify({"error": "Error: Incorrect Passwords"}), 200 + + hashed_password = bcrypt.generate_password_hash( + new_password).decode('utf8') + + user.password_hash = hashed_password + user.passwordpinallowed = 0 + + db.session.add(user) + db.session.commit() + return jsonify({"ok": "success"}), 200 + diff --git a/app/classes/__init__.py b/app/classes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/classes/admin.py b/app/classes/admin.py new file mode 100644 index 0000000..dbf5b75 --- /dev/null +++ b/app/classes/admin.py @@ -0,0 +1,26 @@ +from app import db, ma +from datetime import datetime + + +class Admin_Company(db.Model): + __tablename__ = 'admin_company' + __bind_key__ = 'eamco' + __table_args__ = {"schema": "public"} + + id = db.Column(db.Integer, + primary_key=True, + autoincrement=True, + unique=False) + creation_date = db.Column(db.TIMESTAMP(), default=datetime.utcnow()) + account_prefix = db.Column(db.VARCHAR(5)) + company_name = db.Column(db.VARCHAR(250)) + company_address = db.Column(db.VARCHAR(250)) + company_town = db.Column(db.VARCHAR(100)) + company_zip = db.Column(db.VARCHAR(25)) + company_state = db.Column(db.INTEGER()) + company_phone_number = db.Column(db.VARCHAR(50)) + +class Admin_Company_schema(ma.SQLAlchemyAutoSchema): + class Meta: + model = Admin_Company + diff --git a/app/classes/auth.py b/app/classes/auth.py new file mode 100644 index 0000000..756cf02 --- /dev/null +++ b/app/classes/auth.py @@ -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 \ No newline at end of file diff --git a/app/classes/auto.py b/app/classes/auto.py new file mode 100644 index 0000000..f7e713a --- /dev/null +++ b/app/classes/auto.py @@ -0,0 +1,49 @@ + +from app import db, ma +from datetime import datetime + + +class Auto_Temp(db.Model): + __tablename__ = 'auto_temp' + __bind_key__ = 'eamco' + __table_args__ = {"schema": "public"} + + id = db.Column(db.Integer, + primary_key=True, + autoincrement=True, + unique=False) + todays_date = db.Column(db.TIMESTAMP(), default=datetime.utcnow()) + temp = db.Column(db.DECIMAL(50, 2)) + temp_max = db.Column(db.DECIMAL(50, 2)) + temp_min = db.Column(db.DECIMAL(50, 2)) + temp_avg = db.Column(db.DECIMAL(50, 2)) + degree_day = db.Column(db.INTEGER()) + +class Auto_Temp_schema(ma.SQLAlchemyAutoSchema): + class Meta: + model = Auto_Temp + + + +class Auto_Delivery(db.Model): + __tablename__ = 'auto_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_full_name = db.Column(db.DECIMAL(50, 2)) + last_fill = db.Column(db.TIMESTAMP()) + last_updated = db.Column(db.TIMESTAMP()) + estimated_gallons_left = db.Column(db.INTEGER()) + estimated_gallons_left_prev_day = db.Column(db.INTEGER()) + tank_height = db.Column(db.VARCHAR(25)) + tank_size = db.Column(db.VARCHAR(25)) + k_factor = db.Column(db.DECIMAL(50, 2)) + +class Auto_Delivery_schema(ma.SQLAlchemyAutoSchema): + class Meta: + model = Auto_Delivery diff --git a/app/classes/cards.py b/app/classes/cards.py new file mode 100644 index 0000000..810ae91 --- /dev/null +++ b/app/classes/cards.py @@ -0,0 +1,29 @@ + +from app import db, ma +from datetime import datetime + + +class Card_Card(db.Model): + __tablename__ = 'card_card' + __bind_key__ = 'eamco' + __table_args__ = {"schema": "public"} + + id = db.Column(db.Integer, + primary_key=True, + autoincrement=True, + unique=False) + date_added = db.Column(db.TIMESTAMP(), default=datetime.utcnow()) + user_id = db.Column(db.INTEGER()) + card_number = db.Column(db.VARCHAR(50)) + last_four_digits = db.Column(db.INTEGER()) + name_on_card = db.Column(db.VARCHAR(500)) + expiration_month = db.Column(db.INTEGER()) + expiration_year = db.Column(db.INTEGER()) + type_of_card = db.Column(db.VARCHAR(500)) + security_number = db.Column(db.INTEGER()) + accepted_or_declined = db.Column(db.INTEGER()) + main_card = db.Column(db.BOOLEAN()) + +class Card_Card_schema(ma.SQLAlchemyAutoSchema): + class Meta: + model = Card_Card diff --git a/app/classes/company.py b/app/classes/company.py new file mode 100644 index 0000000..362bac5 --- /dev/null +++ b/app/classes/company.py @@ -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 + diff --git a/app/classes/customer.py b/app/classes/customer.py new file mode 100644 index 0000000..bdb78f2 --- /dev/null +++ b/app/classes/customer.py @@ -0,0 +1,82 @@ + +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) + account_number = db.Column(db.VARCHAR(25)) + 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 \ No newline at end of file diff --git a/app/classes/delivery.py b/app/classes/delivery.py new file mode 100644 index 0000000..c6bab7c --- /dev/null +++ b/app/classes/delivery.py @@ -0,0 +1,117 @@ +from app import db, ma +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.DECIMAL(50, 2)) + # 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 + # issue = 5 + + # finalized = 10 + 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 = 1 + payment_type = db.Column(db.INTEGER) + payment_card_id = db.Column(db.INTEGER) + + driver_employee_id = db.Column(db.VARCHAR(140)) + driver_first_name = db.Column(db.VARCHAR(140)) + driver_last_name = db.Column(db.VARCHAR(140)) + + pre_charge_amount = db.Column(db.DECIMAL(50, 2)) + total_price = db.Column(db.DECIMAL(50, 2)) + final_price = db.Column(db.DECIMAL(50, 2)) + +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 diff --git a/app/classes/employee.py b/app/classes/employee.py new file mode 100644 index 0000000..9498c2e --- /dev/null +++ b/app/classes/employee.py @@ -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 diff --git a/app/classes/pricing.py b/app/classes/pricing.py new file mode 100644 index 0000000..c18b501 --- /dev/null +++ b/app/classes/pricing.py @@ -0,0 +1,49 @@ +from app import db, ma, login_manager +from datetime import datetime + + +class Pricing_Service_General(db.Model): + __tablename__ = 'pricing_service_general' + __bind_key__ = 'eamco' + __table_args__ = {"schema": "public"} + + id = db.Column(db.Integer, + primary_key=True, + autoincrement=True, + unique=False) + + price_service_hour = db.Column(db.DECIMAL(50, 2)) + price_emergency_service_hour = db.Column(db.DECIMAL(50, 2)) + price_emergency_call = db.Column(db.DECIMAL(50, 2)) + price_out_of_oil = db.Column(db.DECIMAL(50, 2)) + price_prime = db.Column(db.DECIMAL(50, 2)) + price_same_day = db.Column(db.DECIMAL(50, 2)) + price_cleaning = db.Column(db.DECIMAL(50, 2)) + date = db.Column(db.TIMESTAMP(), default=datetime.utcnow()) + + +class Pricing_Service_General_schema(ma.SQLAlchemyAutoSchema): + class Meta: + model = Pricing_Service_General + + +class Pricing_Oil_Oil(db.Model): + __tablename__ = 'pricing_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 Pricing_Oil_Oil_schema(ma.SQLAlchemyAutoSchema): + class Meta: + model = Pricing_Oil_Oil + diff --git a/app/classes/query.py b/app/classes/query.py new file mode 100644 index 0000000..d25021d --- /dev/null +++ b/app/classes/query.py @@ -0,0 +1,88 @@ + +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() + + + +class Query_DeliveryStatusList(db.Model): + __tablename__ = 'query_delivery_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_DeliveryStatusList_Schema(ma.SQLAlchemyAutoSchema): + class Meta: + model = Query_DeliveryStatusList + id = ma.auto_field() + text = ma.auto_field() + value = ma.auto_field() diff --git a/app/classes/service.py b/app/classes/service.py new file mode 100644 index 0000000..8bb7298 --- /dev/null +++ b/app/classes/service.py @@ -0,0 +1,126 @@ + +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)) + + payment_type = db.Column(db.INTEGER) + payment_card_id = db.Column(db.INTEGER) + + +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)) + + +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 + + + diff --git a/app/classes/stats_customer.py b/app/classes/stats_customer.py new file mode 100644 index 0000000..3d7151e --- /dev/null +++ b/app/classes/stats_customer.py @@ -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 diff --git a/app/classes/stats_employee.py b/app/classes/stats_employee.py new file mode 100644 index 0000000..b6ee3cd --- /dev/null +++ b/app/classes/stats_employee.py @@ -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 diff --git a/app/classes/stripe.py b/app/classes/stripe.py new file mode 100644 index 0000000..9494bad --- /dev/null +++ b/app/classes/stripe.py @@ -0,0 +1,27 @@ +from app import db, ma +from datetime import datetime + + + +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 + diff --git a/app/common/__init__.py b/app/common/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/common/decorators.py b/app/common/decorators.py new file mode 100644 index 0000000..5cf0c50 --- /dev/null +++ b/app/common/decorators.py @@ -0,0 +1,16 @@ +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 diff --git a/app/customer/__init__.py b/app/customer/__init__.py new file mode 100644 index 0000000..d816b17 --- /dev/null +++ b/app/customer/__init__.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from flask import Blueprint + + +customer = Blueprint('customer', __name__) + + +from . import views \ No newline at end of file diff --git a/app/customer/views.py b/app/customer/views.py new file mode 100644 index 0000000..4e13bdd --- /dev/null +++ b/app/customer/views.py @@ -0,0 +1,198 @@ +from flask import request, jsonify +from flask_login import login_required +from app.customer import customer +from app import db +from datetime import datetime +from app.classes.cards import Card_Card +from app.classes.customer import \ + Customer_Customer, \ + Customer_Customer_schema +from app.classes.admin import Admin_Company +import string +import random + +@customer.route("/all", methods=["GET"]) +@login_required +def all_customers_around(): + customer_list = db.session \ + .query(Customer_Customer) \ + .all() + customer_schema = Customer_Customer_schema(many=True) + return jsonify(customer_schema.dump(customer_list)) + + +@customer.route("/all/", methods=["GET"]) +@login_required +def all_customers(page): + """ + pagination all customers + """ + + per_page_amount = 50 + if page is None: + offset_limit = 0 + elif page == 1: + offset_limit = 0 + else: + offset_limit = (per_page_amount * page) - per_page_amount + + customer_list = db.session \ + .query(Customer_Customer) \ + .limit(per_page_amount).offset(offset_limit) + + customer_schema = Customer_Customer_schema(many=True) + return jsonify(customer_schema.dump(customer_list)) + + +@customer.route("/", methods=["GET"]) +def get_a_customer(customer_id): + """ + Checks auth token to ensure user is authenticated + """ + get_customer = (db.session + .query(Customer_Customer) + .filter(Customer_Customer.id == customer_id) + .first()) + print(get_customer) + customer_schema = Customer_Customer_schema(many=False) + return jsonify(customer_schema.dump(get_customer)) + +def id_generator(size=6, chars=string.ascii_uppercase + string.digits): + return ''.join(random.choice(chars) for _ in range(size)) + +@customer.route("/create", methods=["POST"]) +@login_required +def create_customer(): + """ + """ + now = datetime.utcnow() + get_company = db.session.query(Admin_Company).filter(Admin_Company.id == 1).first() + + starter_digits = str(get_company.account_prefix) + '-' + id_generator() + + made_account_number = starter_digits + + response_customer_last_name = request.json["customer_last_name"] + response_customer_first_name = request.json["customer_first_name"] + response_customer_town = request.json["customer_town"] + response_customer_state = request.json["customer_state"] + response_customer_zip = request.json["customer_zip"] + response_customer_email = request.json["customer_email"] + response_customer_automatic = request.json["customer_automatic"] + response_customer_home_type = request.json["customer_home_type"] + customer_phone_number = request.json["customer_phone_number"] + customer_address = request.json["customer_address"] + customer_apt = request.json["customer_apt"] + if response_customer_automatic is True: + auto_customer = 1 + else: + auto_customer = 0 + + int_customer_home_type = int(response_customer_home_type) + response_customer_zip = int(response_customer_zip) + response_customer_state = int(response_customer_state) + + new_customer = Customer_Customer( + account_number=made_account_number, + customer_last_name=response_customer_last_name, + customer_first_name=response_customer_first_name, + customer_town=response_customer_town, + customer_state=response_customer_state, + customer_zip=response_customer_zip, + customer_first_call=now, + customer_email=response_customer_email, + customer_automatic=auto_customer, + customer_home_type=int_customer_home_type, + customer_phone_number=customer_phone_number, + customer_address=customer_address, + customer_apt=customer_apt + + ) + + db.session.add(new_customer) + db.session.commit() + + return jsonify({ + "ok": True, + 'user': { + 'user_id': new_customer.id, + 'user_name': new_customer.customer_last_name, + 'user_email': new_customer.customer_email, + }, + }), 200 + + +@customer.route("/edit/", methods=["PUT"]) +@login_required +def edit_customer(customer_id): + """ + """ + get_customer = (db.session + .query(Customer_Customer) + .filter(Customer_Customer.id == customer_id) + .first()) + response_customer_last_name = request.json["customer_last_name"] + response_customer_first_name = request.json["customer_first_name"] + response_customer_town = request.json["customer_town"] + response_customer_state = request.json["customer_state"] + response_customer_zip = request.json["customer_zip"] + response_customer_phone_number = request.json["customer_phone_number"] + response_customer_email = request.json["customer_email"] + response_customer_automatic = request.json["customer_automatic"] + response_customer_home_type = request.json["customer_home_type"] + response_customer_address = request.json["customer_address"] + + get_customer.customer_address = response_customer_address + get_customer.customer_home_type = response_customer_home_type + get_customer.customer_automatic = response_customer_automatic + get_customer.customer_phone_number = response_customer_phone_number + get_customer.customer_last_name = response_customer_last_name + get_customer.customer_first_name = response_customer_first_name + get_customer.customer_town = response_customer_town + get_customer.customer_state = response_customer_state + get_customer.customer_zip = response_customer_zip + get_customer.customer_email = response_customer_email + + db.session.add(get_customer) + db.session.commit() + + return jsonify({ + "ok": True, + 'user': { + 'user_name': get_customer.customer_last_name, + + 'user_email': get_customer.customer_email, + }, + }), 200 + + +@customer.route("/delete/", methods=["DELETE"]) +@login_required +def delete_customer(customer_id): + """ + """ + get_customer = (db.session + .query(Customer_Customer) + .filter(Customer_Customer.id == customer_id) + .first()) + + get_cards = (db.session + .query(Card_Card) + .filter(Card_Card.user_id == get_customer.id) + .first()) + + if get_cards is not None: + db.session.delete(get_cards) + + db.session.delete(get_customer) + db.session.commit() + print("deleted") + return jsonify({ + "ok": True, + 'user': { + 'user_name': get_customer.customer_last_name, + 'user_email': get_customer.customer_email, + }, + }), 200 + + diff --git a/app/delivery/__init__.py b/app/delivery/__init__.py new file mode 100644 index 0000000..2d6506a --- /dev/null +++ b/app/delivery/__init__.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from flask import Blueprint + + +delivery = Blueprint('delivery', __name__) + + +from . import views \ No newline at end of file diff --git a/app/delivery/views.py b/app/delivery/views.py new file mode 100644 index 0000000..916b590 --- /dev/null +++ b/app/delivery/views.py @@ -0,0 +1,686 @@ +from flask import request, jsonify +from flask_login import current_user +from datetime import date +from app.delivery import delivery +from app import db +from datetime import datetime +from app.classes.customer import Customer_Customer +from app.classes.delivery import (Delivery_Delivery, + Delivery_Delivery_schema, + Delivery_Notes_Driver, + Delivery_Payment, + Delivery_Payment_schema, + ) +from app.classes.cards import Card_Card +from app.classes.pricing import Pricing_Oil_Oil +from app.classes.auth import Auth_User +from app.classes.pricing import Pricing_Service_General + +@delivery.route("/", methods=["GET"]) +def get_a_delivery(delivery_id): + """ + """ + + get_delivery = db.session\ + .query(Delivery_Delivery)\ + .filter(Delivery_Delivery.id == delivery_id)\ + .first() + + return jsonify({ + "ok": True, + 'delivery': { + 'id': get_delivery.id, + 'customer_id': get_delivery.customer_id, + 'delivery_expected_delivery_date': str(get_delivery.expected_delivery_date), + 'delivery_asked_for_fill': get_delivery.customer_asked_for_fill, + 'delivery_gallons_ordered': get_delivery.gallons_ordered, + 'delivery_dispatcher_notes': get_delivery.dispatcher_notes, + 'delivery_prime': get_delivery.prime, + 'delivery_same_day': get_delivery.same_day, + 'when_ordered': get_delivery.when_ordered, + 'customer_price': get_delivery.customer_price, + 'delivery_status': get_delivery.delivery_status, + 'payment_type': get_delivery.payment_type, + 'payment_card_id': get_delivery.payment_card_id, + + }, + }), 200 + +@delivery.route("/order/", methods=["GET"]) +def get_a_specific_delivery(delivery_id): + + get_delivery = db.session\ + .query(Delivery_Delivery)\ + .filter(Delivery_Delivery.id == delivery_id)\ + .first() + delivery_schema = Delivery_Delivery_schema(many=False) + return jsonify(delivery_schema.dump(get_delivery)) + + +@delivery.route("/order/money/", methods=["GET"]) +def get_a_specific_delivery_money(delivery_id): + + get_delivery_money = db.session\ + .query(Delivery_Payment)\ + .filter(Delivery_Payment.id == delivery_id)\ + .first() + delivery_schema = Delivery_Payment_schema(many=False) + return jsonify(delivery_schema.dump(get_delivery_money)) + + +@delivery.route("/cash//", methods=["PUT"]) +def update_a_delivery_payment(delivery_id, type_of_payment): + """ + This update a delivery for example if user updates to a fill + """ + + get_delivery = (db.session + .query(Delivery_Delivery) + .filter(Delivery_Delivery.id == delivery_id) + .first()) + + get_delivery.payment_type = type_of_payment + + db.session.add(get_delivery) + db.session.commit() + + return jsonify({"ok": True}), 200 + + +@delivery.route("/all", methods=["GET"]) +def get_deliveries_not_delivered_all(): + """ + This will get deliveries not done + """ + + deliveries = db.session \ + .query(Delivery_Delivery) \ + .filter(Delivery_Delivery.delivery_status != 1) \ + .filter(Delivery_Delivery.delivery_status != 3) \ + .all() + + customer_schema = Delivery_Delivery_schema(many=True) + return jsonify(customer_schema.dump(deliveries)) + + +@delivery.route("/customer//", methods=["GET"]) +def get_deliveries_from_customer(customer_id, page): + """ + This will get deliveries not done + """ + per_page_amount = 50 + if page is None: + offset_limit = 0 + elif page == 1: + offset_limit = 0 + else: + offset_limit = (per_page_amount * page) - per_page_amount + + deliveries = db.session \ + .query(Delivery_Delivery) \ + .filter(Delivery_Delivery.customer_id == customer_id) \ + .limit(per_page_amount).offset(offset_limit) + + customer_schema = Delivery_Delivery_schema(many=True) + return jsonify(customer_schema.dump(deliveries)) + +@delivery.route("/all/", methods=["GET"]) +def get_deliveries_not_delivered(page): + + """ + This will get deliveries not done + """ + per_page_amount = 50 + if page is None: + offset_limit = 0 + elif page == 1: + offset_limit = 0 + else: + offset_limit = (per_page_amount * page) - per_page_amount + + deliveries = db.session\ + .query(Delivery_Delivery)\ + .filter(Delivery_Delivery.delivery_status == 0)\ + .order_by(Delivery_Delivery.when_ordered.desc())\ + .limit(per_page_amount).offset(offset_limit) + + customer_schema = Delivery_Delivery_schema(many=True) + return jsonify(customer_schema.dump(deliveries)) + +@delivery.route("/waiting/", methods=["GET"]) +def get_deliveries_waiting(page): + """ + This will get deliveries not done + """ + per_page_amount = 50 + if page is None: + offset_limit = 0 + elif page == 1: + offset_limit = 0 + else: + offset_limit = (per_page_amount * page) - per_page_amount + + deliveries = db.session \ + .query(Delivery_Delivery) \ + .filter(Delivery_Delivery.delivery_status == 0) \ + .order_by(Delivery_Delivery.when_ordered.desc()) \ + .limit(per_page_amount).offset(offset_limit) + + customer_schema = Delivery_Delivery_schema(many=True) + return jsonify(customer_schema.dump(deliveries)) + +@delivery.route("/delivered/", methods=["GET"]) +def get_deliveries_delivered(page): + """ + This will get deliveries not done + """ + per_page_amount = 50 + if page is None: + offset_limit = 0 + elif page == 1: + offset_limit = 0 + else: + offset_limit = (per_page_amount * page) - per_page_amount + + deliveries = db.session \ + .query(Delivery_Delivery) \ + .filter(Delivery_Delivery.delivery_status == 1) \ + .order_by(Delivery_Delivery.when_ordered.desc()) \ + .limit(per_page_amount).offset(offset_limit) + + customer_schema = Delivery_Delivery_schema(many=True) + return jsonify(customer_schema.dump(deliveries)) + +@delivery.route("/outfordelivery/", methods=["GET"]) +def get_deliveries_outfordelivery(page): + """ + This will get deliveries not done + """ + per_page_amount = 50 + if page is None: + offset_limit = 0 + elif page == 1: + offset_limit = 0 + else: + offset_limit = (per_page_amount * page) - per_page_amount + + deliveries = db.session \ + .query(Delivery_Delivery) \ + .filter(Delivery_Delivery.delivery_status == 2) \ + .order_by(Delivery_Delivery.when_ordered.desc()) \ + .limit(per_page_amount).offset(offset_limit) + + customer_schema = Delivery_Delivery_schema(many=True) + return jsonify(customer_schema.dump(deliveries)) + +@delivery.route("/finalized/", methods=["GET"]) +def get_deliveries_finalized(page): + """ + This will get deliveries not done + """ + per_page_amount = 50 + if page is None: + offset_limit = 0 + elif page == 1: + offset_limit = 0 + else: + offset_limit = (per_page_amount * page) - per_page_amount + + deliveries = db.session \ + .query(Delivery_Delivery) \ + .filter(Delivery_Delivery.delivery_status == 10) \ + .order_by(Delivery_Delivery.when_ordered.desc()) \ + .limit(per_page_amount).offset(offset_limit) + + customer_schema = Delivery_Delivery_schema(many=True) + return jsonify(customer_schema.dump(deliveries)) + + + +@delivery.route("/cancelled/", methods=["GET"]) +def get_deliveries_cancelled(page): + """ + This will get deliveries not done + """ + per_page_amount = 50 + if page is None: + offset_limit = 0 + elif page == 1: + offset_limit = 0 + else: + offset_limit = (per_page_amount * page) - per_page_amount + + deliveries = db.session \ + .query(Delivery_Delivery) \ + .filter(Delivery_Delivery.delivery_status == 3) \ + .order_by(Delivery_Delivery.when_ordered.desc()) \ + .limit(per_page_amount).offset(offset_limit) + + customer_schema = Delivery_Delivery_schema(many=True) + return jsonify(customer_schema.dump(deliveries)) + + +@delivery.route("/partialdelivery/", methods=["GET"]) +def get_deliveries_partial(page): + """ + This will get deliveries not done + """ + per_page_amount = 50 + if page is None: + offset_limit = 0 + elif page == 1: + offset_limit = 0 + else: + offset_limit = (per_page_amount * page) - per_page_amount + + deliveries = db.session \ + .query(Delivery_Delivery) \ + .filter(Delivery_Delivery.delivery_status == 4) \ + .order_by(Delivery_Delivery.when_ordered.desc()) \ + .limit(per_page_amount).offset(offset_limit) + + customer_schema = Delivery_Delivery_schema(many=True) + return jsonify(customer_schema.dump(deliveries)) + +@delivery.route("/issue/", methods=["GET"]) +def get_deliveries_issue(page): + """ + This will get deliveries not done + """ + per_page_amount = 50 + if page is None: + offset_limit = 0 + elif page == 1: + offset_limit = 0 + else: + offset_limit = (per_page_amount * page) - per_page_amount + + deliveries = db.session \ + .query(Delivery_Delivery) \ + .filter(Delivery_Delivery.delivery_status == 5) \ + .order_by(Delivery_Delivery.when_ordered.desc()) \ + .limit(per_page_amount).offset(offset_limit) + + customer_schema = Delivery_Delivery_schema(many=True) + return jsonify(customer_schema.dump(deliveries)) + + +@delivery.route("/time/today", methods=["GET"]) +def get_deliveries_today(): + """ + This will get today's deliveries + """ + + deliveries = db.session \ + .query(Delivery_Delivery) \ + .filter(Delivery_Delivery.expected_delivery_date == date.today()) \ + .all() + + customer_schema = Delivery_Delivery_schema(many=True) + return jsonify(customer_schema.dump(deliveries)) + +@delivery.route("/amount/", methods=["GET"]) +def get_deliveries_amount_total(delivery_id): + """ + This will get deliveries totals + """ + + delivery_amount = db.session \ + .query(Delivery_Payment) \ + .filter(Delivery_Payment.delivery_id == delivery_id) \ + .all() + + delivery_schema = Delivery_Delivery_schema(many=False) + return jsonify(delivery_schema.dump(delivery_amount)) + + +@delivery.route("/edit/", methods=["POST"]) +def edit_a_delivery(delivery_id): + """ + This will create a delivery using a customer id + """ + get_delivery = db.session \ + .query(Delivery_Delivery) \ + .filter(Delivery_Delivery.id == delivery_id) \ + .first() + + get_today_price = db.session \ + .query(Pricing_Oil_Oil) \ + .order_by(Pricing_Oil_Oil.id.desc()) \ + .first() + + get_customer = db.session \ + .query(Customer_Customer) \ + .filter(Customer_Customer.id == get_delivery.customer_id) \ + .first() + + if not get_delivery: + return jsonify({"ok": False}), 200 + else: + + gallons_ordered = request.json["gallons_ordered"] + delivery_status = request.json["delivery_status"] + when_to_deliver = request.json["expected_delivery_date"] + dispatcher_notes_taken = request.json["dispatcher_notes_taken"] + + customer_wants_fill = request.json["customer_asked_for_fill"] + + card_payment = request.json["credit"] + cash_payment = request.json["cash"] + + + if request.json["credit_card_id"]: + card_payment_id = request.json["credit_card_id"] + else: + card_payment_id = None + + + if card_payment_id is not None: + get_card = (db.session + .query(Card_Card) + .filter(Card_Card.id == card_payment_id) + .filter(Card_Card.user_id == get_customer.id) + .first()) + card_id_from_customer = get_card.id + else: + card_id_from_customer = None + + if cash_payment is True and card_payment is False: + delivery_payment_method = 0 + elif card_payment is True and cash_payment is False: + delivery_payment_method = 1 + + elif card_payment is True and cash_payment is True: + delivery_payment_method = 2 + else: + delivery_payment_method = 3 + + if customer_wants_fill is True: + customer_wants_fill = 1 + else: + customer_wants_fill = 0 + + same_day_info = request.json["same_day"] + if same_day_info is True: + same_day_info = 1 + else: + same_day_info = 0 + + prime_info = request.json["prime"] + if prime_info is True: + prime_info = 1 + else: + prime_info = 0 + + get_delivery.delivery_status = delivery_status + get_delivery.gallons_ordered = gallons_ordered + get_delivery.customer_asked_for_fill = customer_wants_fill + get_delivery.expected_delivery_date = when_to_deliver + get_delivery.dispatcher_notes = dispatcher_notes_taken + get_delivery.prime = prime_info + get_delivery.same_day = same_day_info + get_delivery.gallons_ordered = gallons_ordered + get_delivery.payment_type = delivery_payment_method + get_delivery.payment_card_id = card_id_from_customer + + db.session.add(get_delivery) + db.session.commit() + + return jsonify({ + "ok": True, + 'customer': { + 'user_id': get_customer.id, + }, + }), 200 + + +@delivery.route("/create/", methods=["POST"]) +def create_a_delivery(user_id): + """ + This will create a delivery using a customer id + """ + get_customer = db.session\ + .query(Customer_Customer)\ + .filter(Customer_Customer.id == user_id)\ + .first() + + get_today_price = db.session\ + .query(Pricing_Oil_Oil)\ + .order_by(Pricing_Oil_Oil.id.desc())\ + .first() + + get_service_prices = (db.session + .query(Pricing_Service_General) + .order_by(Pricing_Service_General.id.desc()) + .first()) + if not get_customer: + return jsonify({"ok": False}), 200 + else: + gallons_ordered = request.json["gallons_ordered"] + customer_wants_fill = request.json["customer_asked_for_fill"] + when_to_deliver = request.json["expected_delivery_date"] + dispatcher_notes_taken = request.json["dispatcher_notes_taken"] + prime_info = request.json["prime"] + same_day_info = request.json["same_day"] + + card_payment = request.json["credit"] + cash_payment = request.json["cash"] + try: + if request.json["credit_card_id"]: + card_payment_id = request.json["credit_card_id"] + else: + card_payment_id = None + except: + card_payment_id = None + + if card_payment_id is not None: + get_card = (db.session + .query(Card_Card) + .filter(Card_Card.id == card_payment_id) + .filter(Card_Card.user_id == get_customer.id) + .first()) + card_id_from_customer = get_card.id + else: + card_id_from_customer = None + + if cash_payment is True and card_payment is False: + delivery_payment_method = 0 + elif card_payment is True and cash_payment is False: + delivery_payment_method = 1 + + elif card_payment is True and cash_payment is True: + delivery_payment_method = 2 + else: + delivery_payment_method = 3 + + if customer_wants_fill is True: + customer_fill_up = 1 + gallons_ordered = 250 + else: + customer_fill_up = 0 + + if prime_info is True: + prime_asked = 1 + else: + prime_asked = 0 + + if same_day_info is True: + same_day_asked = 1 + else: + same_day_asked = 0 + + date_object = datetime.strptime(when_to_deliver, '%Y-%m-%d').date() + + customer_filled_name = get_customer.customer_last_name + ' ' + get_customer.customer_first_name + now = datetime.utcnow() + + + # Pricing + if customer_fill_up == 1: + precharge_amount = (250 * get_today_price.price_for_customer) + else: + precharge_amount = int(gallons_ordered) * get_today_price.price_for_customer + + if same_day_asked == 1 and prime_asked == 0: + total_precharge_amount = precharge_amount + get_service_prices.price_same_day + + elif prime_asked == 1 and same_day_asked == 0: + total_precharge_amount = precharge_amount + get_service_prices.price_prime + + else: + total_precharge_amount = precharge_amount + get_service_prices.price_prime + get_service_prices.price_same_day + + + new_delivery = Delivery_Delivery( + customer_id=get_customer.id, + customer_address=get_customer.customer_address, + customer_name=customer_filled_name, + customer_town=get_customer.customer_town, + customer_state=get_customer.customer_state, + customer_zip=get_customer.customer_zip, + gallons_ordered=gallons_ordered, + customer_asked_for_fill=customer_fill_up, + gallons_delivered=0, + customer_filled=0, + delivery_status=0, + when_ordered=now, + when_delivered=None, + expected_delivery_date=date_object, + automatic=get_customer.customer_automatic, + oil_id=get_today_price.id, + supplier_price=get_today_price.price_from_supplier, + customer_price=get_today_price.price_for_customer, + customer_temperature=None, + dispatcher_notes=dispatcher_notes_taken, + prime=prime_asked, + same_day=same_day_asked, + payment_type=delivery_payment_method, + payment_card_id=card_id_from_customer, + pre_charge_amount=total_precharge_amount, + total_price=precharge_amount, + final_price=0, + + ) + + db.session.add(new_delivery) + db.session.commit() + + return jsonify({ + "ok": True, + 'delivery_id': new_delivery.id, + }), 200 + + + +@delivery.route("/cancel/", methods=["POST"]) +def cancel_a_delivery(delivery_id): + """ + This will cancel a delivery + """ + get_delivery = db.session\ + .query(Delivery_Delivery)\ + .filter(Delivery_Delivery.id == delivery_id)\ + .first() + + get_delivery.delivery_status = 3 + db.session.add(get_delivery) + db.session.commit() + + return jsonify({"ok": True}), 200 + + +@delivery.route("/delivered/", methods=["POST"]) +def mark_as_delivered(delivery_id): + """ + This will mark the delivery as delivered + """ + # how many gallons delivered + gallons_put_into_tank = request.json["gallons_put_into_tank"] + # was the tank full or not + was_it_filled = request.json["filled"] + + get_delivery = db.session\ + .query(Delivery_Delivery)\ + .filter(Delivery_Delivery.id == delivery_id)\ + .first() + + get_delivery.delivery_status = 1 + get_delivery.gallons_delivered = gallons_put_into_tank + get_delivery.customer_filled = was_it_filled + + db.session.add(get_delivery) + db.session.commit() + + return jsonify({"ok": True}), 200 + + +@delivery.route("/partial/", methods=["POST"]) +def partial_delivery(delivery_id): + """ + This will mark the delivery as delivered + """ + # how many gallons delivered + gallons_put_into_tank = request.json["gallons_put_into_tank"] + + get_delivery = db.session\ + .query(Delivery_Delivery)\ + .filter(Delivery_Delivery.id == delivery_id)\ + .first() + + get_delivery.delivery_status = 4 + get_delivery.gallons_delivered = gallons_put_into_tank + get_delivery.customer_filled = 0 + + db.session.add(get_delivery) + db.session.commit() + + return jsonify({"ok": True}), 200 + + +@delivery.route("/note/technician/", methods=["PUT"]) +def delivery_note_driver(delivery_id): + + """ + Update a service call diagnosis + """ + # + driver_notes = request.json["driver_notes"] + now = datetime.utcnow() + + user = db.session\ + .query(Auth_User)\ + .filter(Auth_User.id == current_user.id)\ + .first() + + get_delivery = db.session\ + .query(Delivery_Delivery)\ + .filter(Delivery_Delivery.id == delivery_id)\ + .first() + + create_new_note = Delivery_Notes_Driver( + delivery_id=get_delivery.id, + driver_comments=driver_notes, + time_added=now, + driver_id=user.id, + driver_name=user.user, + ) + + db.session.add(create_new_note) + db.session.commit() + + return jsonify({"ok": True}), 200 + + +@delivery.route("/delete/", methods=["DELETE"]) +def service_delete_call(delivery_id): + """ + delete a delivery call + """ + get_call_to_delete = (db.session + .query(Delivery_Delivery) + .filter(Delivery_Delivery.id == delivery_id) + .first()) + db.session.delete(get_call_to_delete) + db.session.commit() + + return jsonify({"ok": True}), 200 \ No newline at end of file diff --git a/app/delivery_data/__init__.py b/app/delivery_data/__init__.py new file mode 100644 index 0000000..b0bf3d6 --- /dev/null +++ b/app/delivery_data/__init__.py @@ -0,0 +1,7 @@ +# coding=utf-8 + +from flask import Blueprint + +delivery_data = Blueprint('delivery_data', __name__) + +from . import views \ No newline at end of file diff --git a/app/delivery_data/views.py b/app/delivery_data/views.py new file mode 100644 index 0000000..d3aa6f4 --- /dev/null +++ b/app/delivery_data/views.py @@ -0,0 +1,123 @@ +from flask import request, jsonify +from flask_login import current_user +from datetime import date +from app.delivery_data import delivery_data +from app import db +from datetime import datetime +from app.classes.customer import Customer_Customer +from app.classes.delivery import (Delivery_Delivery, + Delivery_Delivery_schema, + Delivery_Notes_Driver, + Delivery_Payment, + Delivery_Payment_schema, + ) +from app.classes.cards import Card_Card +from app.classes.pricing import Pricing_Oil_Oil +from app.classes.auth import Auth_User +from app.classes.pricing import Pricing_Service_General + + + +@delivery_data.route("/pending", methods=["GET"]) +def pending_delivery(): + """ + Get deliveries that have been delivered + """ + + delivery_ticket = (db.session + .query(Delivery_Delivery) + .filter(Delivery_Delivery.delivery_status!=0) + .all()) + + + delivery_schema = Delivery_Delivery_schema(many=True) + return jsonify(delivery_schema.dump(delivery_ticket)) + + + +@delivery_data.route("/finalize/", methods=["PUT"]) +def finalize_delivery(delivery_id): + """ + Get deliveries that have been delivered + """ + + """ + Finalizes a delivery from office + """ + get_delivery = db.session \ + .query(Delivery_Delivery) \ + .filter(Delivery_Delivery.id == delivery_id) \ + .first() + + get_today_price = db.session \ + .query(Pricing_Oil_Oil) \ + .order_by(Pricing_Oil_Oil.id.desc()) \ + .first() + + get_customer = db.session \ + .query(Customer_Customer) \ + .filter(Customer_Customer.id == get_delivery.customer_id) \ + .first() + + + gallons_delivered = request.json["gallons_delivered"] + card_payment = request.json["credit"] + cash_payment = request.json["cash"] + + if request.json["credit_card_id"]: + card_payment_id = request.json["credit_card_id"] + else: + card_payment_id = None + + + if card_payment_id is not None: + get_card = (db.session + .query(Card_Card) + .filter(Card_Card.id == card_payment_id) + .filter(Card_Card.user_id == get_customer.id) + .first()) + card_id_from_customer = get_card.id + else: + card_id_from_customer = None + + if cash_payment is True and card_payment is False: + delivery_payment_method = 0 + elif card_payment is True and cash_payment is False: + delivery_payment_method = 1 + + elif card_payment is True and cash_payment is True: + delivery_payment_method = 2 + else: + delivery_payment_method = 3 + + + + same_day_info = request.json["same_day"] + if same_day_info is True: + same_day_info = 1 + else: + same_day_info = 0 + + prime_info = request.json["prime"] + if prime_info is True: + prime_info = 1 + else: + prime_info = 0 + + get_delivery.gallons_delivered = gallons_delivered + get_delivery.prime = prime_info + get_delivery.same_day = same_day_info + get_delivery.payment_type = delivery_payment_method + get_delivery.payment_card_id = card_id_from_customer + + get_delivery.delivery_status = 10 + db.session.add(get_delivery) + db.session.commit() + + return jsonify({ + "ok": True, + 'delivery': { + 'id': get_delivery.id, + }, + }), 200 + diff --git a/app/employees/__init__.py b/app/employees/__init__.py new file mode 100644 index 0000000..2ba7e57 --- /dev/null +++ b/app/employees/__init__.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from flask import Blueprint + + +employees = Blueprint('employees', __name__) + + +from . import views \ No newline at end of file diff --git a/app/employees/views.py b/app/employees/views.py new file mode 100644 index 0000000..f569a2d --- /dev/null +++ b/app/employees/views.py @@ -0,0 +1,176 @@ +from flask import request, jsonify +from flask_login import current_user +from sqlalchemy import or_ +from datetime import date, timedelta +from flask_login import login_required +from app.employees import employees +from app import db +from datetime import datetime +from app.classes.employee import Employee_Employee, Employee_Employee_schema + + +@employees.route("/", methods=["GET"]) +@login_required +def get_specific_employee(userid): + employee = db.session \ + .query(Employee_Employee) \ + .filter(Employee_Employee.id == userid) \ + .first() + employee_schema = Employee_Employee_schema(many=False) + return jsonify(employee_schema.dump(employee)) + + +@employees.route("/userid/", methods=["GET"]) +@login_required +def get_specific_employee_user_id(userid): + employee = db.session \ + .query(Employee_Employee) \ + .filter(Employee_Employee.user_id == userid) \ + .first() + # print(employee.id) + employee_schema = Employee_Employee_schema(many=False) + return jsonify(employee_schema.dump(employee)) + + +@employees.route("/all/", methods=["GET"]) +@login_required +def all_employees_paginated(page): + """ + pagination all employees + """ + per_page_amount = 50 + if page is None: + offset_limit = 0 + elif page == 1: + offset_limit = 0 + else: + offset_limit = (per_page_amount * page) - per_page_amount + + employee_list = (db.session + .query(Employee_Employee) \ + .limit(per_page_amount).offset(offset_limit)) + + employee_schema = Employee_Employee_schema(many=True) + return jsonify(employee_schema.dump(employee_list)) + + +@employees.route("/all", methods=["GET"]) +@login_required +def all_employees(): + employee_list = db.session \ + .query(Employee_Employee) \ + .all() + customer_schema = Employee_Employee_schema(many=True) + return jsonify(customer_schema.dump(employee_list)) + + +@employees.route("/drivers", methods=["GET"]) +@login_required +def all_employees_drivers(): + employee_list = db.session \ + .query(Employee_Employee) \ + .filter(Employee_Employee.employee_type == 4) \ + .all() + customer_schema = Employee_Employee_schema(mwany=True) + return jsonify(customer_schema.dump(employee_list)) + + +@employees.route("/techs", methods=["GET"]) +@login_required +def all_employees_techs(): + employee_list = db.session \ + .query(Employee_Employee) \ + .filter(or_(Employee_Employee.employee_type == 0, + Employee_Employee.employee_type == 1, + Employee_Employee.employee_type == 5, + Employee_Employee.employee_type == 8, + )) \ + .all() + customer_schema = Employee_Employee_schema(many=True) + return jsonify(customer_schema.dump(employee_list)) + + +@employees.route("/create", methods=["POST"]) +@login_required +def employee_create(): + """ + This will create an employee + """ + e_last_name = request.json["employee_last_name"] + e_first_name = request.json["employee_first_name"] + e_town = request.json["employee_town"] + e_state = request.json["employee_state"] + e_address = request.json["employee_address"] + e_zip = request.json["employee_zip"] + e_birthday = request.json["employee_birthday"] + e_type = request.json["employee_type"] + e_start_date = request.json["employee_start_date"] + e_end_date = request.json["employee_end_date"] + e_phone_number = request.json["employee_phone_number"] + + emp_state = int(e_state) + emp_type = int(e_type) + emp_zip = int(e_zip) + + if e_end_date == '': + e_end_date = None + + new_employee = Employee_Employee( + + employee_last_name=e_last_name, + employee_first_name=e_first_name, + employee_town=e_town, + employee_state=emp_state, + employee_zip=emp_zip, + employee_address=e_address, + employee_birthday=e_birthday, + employee_type=emp_type, + employee_start_date=e_start_date, + employee_end_date=e_end_date, + employee_phone_number=e_phone_number, + ) + + db.session.add(new_employee) + db.session.commit() + + return jsonify({"ok": True, + 'user_id': new_employee.id, + }), 200 + + +@employees.route("/edit/", methods=["POST"]) +def employee_edit(employee_id): + """ + This will update an employee + """ + e_last_name = request.json["employee_last_name"] + e_first_name = request.json["employee_first_name"] + e_town = request.json["employee_town"] + e_state = request.json["employee_state"] + e_zip = request.json["employee_zip"] + e_birthday = request.json["employee_birthday"] + e_type = request.json["employee_type"] + e_start_date = request.json["employee_start_date"] + e_end_date = request.json["employee_end_date"] + print(request.json["employee_end_date"]) + + get_employee = db.session \ + .query(Employee_Employee) \ + .filter(Employee_Employee.id == employee_id) \ + .first() + + get_employee.employee_first_name = e_first_name + get_employee.employee_last_name = e_last_name + get_employee.employee_town = e_town + get_employee.employee_state = e_state + get_employee.employee_zip = e_zip + get_employee.employee_birthday = e_birthday + get_employee.employee_type = e_type + get_employee.employee_start_date = e_start_date + if e_end_date != 'None': + get_employee.employee_end_date = e_end_date + + db.session.add(get_employee) + db.session.commit() + + return jsonify({"ok": True}), 200 diff --git a/app/info/__init__.py b/app/info/__init__.py new file mode 100644 index 0000000..af33674 --- /dev/null +++ b/app/info/__init__.py @@ -0,0 +1,8 @@ +# coding=utf-8 +from flask import Blueprint + + +info = Blueprint('info', __name__) + + +from . import views \ No newline at end of file diff --git a/app/info/views.py b/app/info/views.py new file mode 100644 index 0000000..9946af4 --- /dev/null +++ b/app/info/views.py @@ -0,0 +1,46 @@ +from flask import jsonify +from app.info import info +from app import db +from app.classes.pricing import Pricing_Oil_Oil, Pricing_Service_General +from app.classes.admin import Admin_Company + + +@info.route("/price/oil", methods=["GET"]) +def get_oil_price(): + get_price_query = (db.session + .query(Pricing_Oil_Oil) + .order_by(Pricing_Oil_Oil.date.desc()) + .first()) + return jsonify({"ok": True, + 'price': get_price_query.price_for_customer, + }), 200 + + +@info.route("/price/service", methods=["GET"]) +def get_service_price(): + get_price_query = (db.session + .query(Pricing_Service_General) + .order_by(Pricing_Service_General.date.desc()) + .first()) + + return jsonify({"ok": True, + 'same_day': get_price_query.price_same_day, + 'price_hourly': get_price_query.price_service_hour, + 'emergency_fee': get_price_query.price_emergency_call, + 'emergency_rate': get_price_query.price_emergency_service_hour, + 'prime': get_price_query.price_prime, + 'cleaning': get_price_query.price_cleaning, + 'out_of_oil': get_price_query.price_out_of_oil, + }), 200 + + +@info.route("/company", methods=["GET"]) +def get_company(): + get_data_company = (db.session + .query(Admin_Company) + .first()) + + return jsonify({"ok": True, + 'name': get_data_company.company_name, + 'telephone': get_data_company.company_phone_number, + }), 200 diff --git a/app/main/__init__.py b/app/main/__init__.py new file mode 100644 index 0000000..812deb1 --- /dev/null +++ b/app/main/__init__.py @@ -0,0 +1,7 @@ +# coding=utf-8 + +from flask import Blueprint + +main = Blueprint('main', __name__) + +from . import views \ No newline at end of file diff --git a/app/main/views.py b/app/main/views.py new file mode 100644 index 0000000..b0ee3b1 --- /dev/null +++ b/app/main/views.py @@ -0,0 +1,19 @@ +from flask import jsonify, Response +from app import app + + +@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 + diff --git a/app/payment/__init__.py b/app/payment/__init__.py new file mode 100644 index 0000000..b00ec16 --- /dev/null +++ b/app/payment/__init__.py @@ -0,0 +1,7 @@ +# coding=utf-8 + +from flask import Blueprint + +payment = Blueprint('payment', __name__) + +from . import views \ No newline at end of file diff --git a/app/payment/views.py b/app/payment/views.py new file mode 100644 index 0000000..ed63fba --- /dev/null +++ b/app/payment/views.py @@ -0,0 +1,206 @@ +from flask import jsonify, request +from app.payment import payment +from app import db +from app.classes.customer import Customer_Customer +from app.classes.cards import Card_Card, Card_Card_schema +from flask_login import current_user + + +def set_card_main(user_id): + """ + updates a card of a user + """ + get_card_count = db.session \ + .query(Card_Card) \ + .filter(Card_Card.user_id == user_id) \ + .count() + print(get_card_count) + if get_card_count > 0: + print("true") + + get_old_card = db.session \ + .query(Card_Card) \ + .filter(Card_Card.main_card == True) \ + .filter(Card_Card.user_id == user_id) \ + .first() + print(get_old_card.id) + + get_old_card.main_card = False + + db.session.add(get_old_card) + + db.session.commit() + + +@payment.route("/cards/", methods=["GET"]) +def get_user_cards(user_id): + """ + gets all cards of a user + """ + get_u_cards = db.session \ + .query(Card_Card) \ + .filter(Card_Card.user_id == user_id) \ + .all() + + card_schema = Card_Card_schema(many=True) + return jsonify(card_schema.dump(get_u_cards)) + + +@payment.route("/cards/onfile/", methods=["GET"]) +def get_user_cards_count(user_id): + """ + gets all cards of a user + """ + + get_u_cards = db.session \ + .query(Card_Card) \ + .filter(Card_Card.user_id == user_id) \ + .count() + + return jsonify({ + "ok": True, + 'cards': get_u_cards, + }), 200 + + +@payment.route("/card/", methods=["GET"]) +def get_user_specific_card(card_id): + """ + gets a specific card of a user + """ + + get_user_card = db.session \ + .query(Card_Card) \ + .filter(Card_Card.id == card_id) \ + .first() + + card_schema = Card_Card_schema(many=False) + return jsonify(card_schema.dump(get_user_card)) + + +@payment.route("/card/create/", methods=["POST"]) +def create_user_card(user_id): + """ + adds a card of a user + """ + + get_customer = db.session \ + .query(Customer_Customer) \ + .filter(Customer_Customer.id == user_id) \ + .first() + + name_on_card = request.json["card_name"] + expiration_month = request.json["expiration_month"] + expiration_year = request.json["expiration_year"] + type_of_card = request.json["type_of_card"] + security_number = request.json["security_number"] + main_card = request.json["main_card"] + + card_number = request.json["card_number"] + last_four = card_number[-4] + + create_new_card = Card_Card( + user_id=get_customer.id, + card_number=card_number, + last_four_digits=last_four, + name_on_card=name_on_card, + expiration_month=expiration_month, + expiration_year=expiration_year, + type_of_card=type_of_card, + security_number=security_number, + accepted_or_declined=None, + main_card=main_card, + ) + print(main_card) + if main_card is True: + set_card_main(user_id=get_customer.id) + db.session.add(create_new_card) + db.session.commit() + + return jsonify({"ok": True}), 200 + + +@payment.route("/card/main//", methods=["PUT"]) +def set_main_card(user_id, card_id): + """ + updates a card of a user + """ + + get_new_main_card = db.session \ + .query(Card_Card) \ + .filter(Card_Card.user_id == user_id) \ + .filter(Card_Card.id == card_id) \ + .first() + + get_other_card = db.session \ + .query(Card_Card) \ + .filter(Card_Card.main_card == True) \ + .filter(Card_Card.user_id == user_id) \ + .first() + if get_other_card is not None: + get_other_card.main_card = False + db.session.add(get_other_card) + get_new_main_card.main_card = True + + db.session.add(get_new_main_card) + db.session.commit() + + return jsonify({"ok": True}), 200 + + +@payment.route("/card/edit/", methods=["PUT"]) +def update_user_card(card_id): + """ + edits a card + """ + + get_card = db.session \ + .query(Card_Card) \ + .filter(Card_Card.id == card_id) \ + .first() + + get_customer = db.session \ + .query(Customer_Customer) \ + .filter(Customer_Customer.id == get_card.user_id) \ + .first() + name_on_card = request.json["card_name"] + expiration_month = request.json["expiration_month"] + expiration_year = request.json["expiration_year"] + type_of_card = request.json["type_of_card"] + security_number = request.json["security_number"] + card_number = request.json["card_number"] + main_card = request.json["main_card"] + + get_card.user_id = get_customer.id + get_card.card_number = card_number + get_card.name_on_card = name_on_card + get_card.expiration_month = expiration_month + get_card.expiration_year = expiration_year + get_card.type_of_card = type_of_card + get_card.security_number = security_number + get_card.main_card = main_card + + if main_card is True: + set_card_main(user_id=get_customer.id, card_id=get_card.id) + + db.session.add(get_card) + db.session.commit() + + return jsonify({"ok": True}), 200 + + +@payment.route("/card/remove/", methods=["DELETE"]) +def remove_user_card(card_id): + """ + removes a card + """ + + get_card = db.session \ + .query(Card_Card) \ + .filter(Card_Card.id == card_id) \ + .first() + + db.session.delete(get_card) + db.session.commit() + + return jsonify({"ok": True}), 200 diff --git a/app/query/__init__.py b/app/query/__init__.py new file mode 100644 index 0000000..ffa3cf9 --- /dev/null +++ b/app/query/__init__.py @@ -0,0 +1,7 @@ +# coding=utf-8 + +from flask import Blueprint + +query = Blueprint('query', __name__) + +from . import views \ No newline at end of file diff --git a/app/query/views.py b/app/query/views.py new file mode 100644 index 0000000..81f0437 --- /dev/null +++ b/app/query/views.py @@ -0,0 +1,82 @@ +from flask import request, jsonify +from flask_login import current_user +from datetime import date, timedelta +from app.query import query +from app import db +from datetime import datetime +from app.classes.query import Query_StateList, \ + Query_DeliveryStatusList, \ + Query_DeliveryStatusList_Schema, \ + Query_StateList_Schema, \ + Query_CustomerTypeList, \ + Query_CustomerTypeList_Schema,\ + Query_EmployeeTypeList, \ + Query_EmployeeTypeList_Schema,\ + Query_ServiceTypeList,\ + Query_ServiceTypeList_Schema + + +@query.route("/states", methods=["GET"]) +def get_state_list(): + """ + This will get states + """ + + query_data = db.session \ + .query(Query_StateList) \ + .all() + + customer_schema = Query_StateList_Schema(many=True) + return jsonify(customer_schema.dump(query_data)) + + +@query.route("/customertype", methods=["GET"]) +def get_customer_type_list(): + """ + This will get types of customers + """ + + query_data = db.session \ + .query(Query_CustomerTypeList) \ + .all() + customer_schema = Query_CustomerTypeList_Schema(many=True) + return jsonify(customer_schema.dump(query_data)) + + +@query.route("/servicetype", methods=["GET"]) +def get_service_type_list(): + """ + This will get types of service + """ + + query_data = db.session \ + .query(Query_ServiceTypeList) \ + .all() + customer_schema = Query_ServiceTypeList_Schema(many=True) + return jsonify(customer_schema.dump(query_data)) + + +@query.route("/employeetype", methods=["GET"]) +def get_employee_type_list(): + """ + This will get types of service + """ + + query_data = db.session \ + .query(Query_EmployeeTypeList) \ + .all() + customer_schema = Query_EmployeeTypeList_Schema(many=True) + return jsonify(customer_schema.dump(query_data)) + + +@query.route("/deliverystatus", methods=["GET"]) +def get_delivery_status_list(): + """ + This will get delivery status + """ + + query_data = db.session \ + .query(Query_DeliveryStatusList) \ + .all() + delivery_schema = Query_DeliveryStatusList_Schema(many=True) + return jsonify(delivery_schema.dump(query_data)) diff --git a/app/reports/__init__.py b/app/reports/__init__.py new file mode 100644 index 0000000..859ffdf --- /dev/null +++ b/app/reports/__init__.py @@ -0,0 +1,7 @@ +# coding=utf-8 + +from flask import Blueprint + +reports = Blueprint('reports', __name__) + +from . import views \ No newline at end of file diff --git a/app/reports/views.py b/app/reports/views.py new file mode 100644 index 0000000..a1e021b --- /dev/null +++ b/app/reports/views.py @@ -0,0 +1,24 @@ +from flask import request, jsonify +from flask_login import current_user +from sqlalchemy.sql import func +from datetime import date, timedelta +from app.reports import reports +from app import db +from datetime import datetime + +from app.classes.auth import Auth_User +from app.classes.customer import Customer_Customer +from app.classes.service import Service_Call, Service_Call_schema +from app.classes.employee import Employee_Employee +from app.classes.service import Service_Call_Notes_Dispatcher, Service_Call_Notes_Technician +from app.classes.delivery import Delivery_Delivery + + +@reports.route("/oil/total", methods=["GET"]) +def oil_total_gallons(): + total_oil = db.session\ + .query(func.sum(Delivery_Delivery.gallons_delivered))\ + .group_by(Delivery_Delivery.id)\ + .all() + + return jsonify({"ok": True }), 200 \ No newline at end of file diff --git a/app/search/__init__.py b/app/search/__init__.py new file mode 100644 index 0000000..466ac51 --- /dev/null +++ b/app/search/__init__.py @@ -0,0 +1,7 @@ +# coding=utf-8 + +from flask import Blueprint + +search = Blueprint('search', __name__) + +from . import views \ No newline at end of file diff --git a/app/search/views.py b/app/search/views.py new file mode 100644 index 0000000..5a0278c --- /dev/null +++ b/app/search/views.py @@ -0,0 +1,79 @@ +from flask import request, jsonify +from flask_login import current_user +from sqlalchemy.sql import func +from datetime import date, timedelta +from app.search import search +from app import db +from datetime import datetime + +from app.classes.auth import Auth_User +from app.classes.customer import Customer_Customer, Customer_Customer_schema +from app.classes.service import Service_Call, Service_Call_schema +from app.classes.employee import Employee_Employee +from app.classes.service import Service_Call_Notes_Dispatcher, Service_Call_Notes_Technician +from app.classes.delivery import Delivery_Delivery, Delivery_Delivery_schema + + +@search.route("/customer", methods=["GET"]) +def search_customers(): + """ + + """ + + keyword = request.args.get('q') + search = "%{}%".format(keyword) + search_type = (search[1]) + search = search.replace("!", "") + search = search.replace("#", "") + search = search.replace("@", "") + # search by last name + if search_type == '@': + search = search[1:] + customer_list = (db.session + .query(Customer_Customer) + .filter(Customer_Customer.customer_first_name.ilike(search)) + .all()) + + elif search_type == '!': + + search = search[::1] + customer_list = (db.session + .query(Customer_Customer) + .filter(Customer_Customer.customer_address.ilike(search)) + .all()) + # Phone Number + elif search_type == '#': + search = search[::1] + customer_list = (db.session + .query(Customer_Customer) + .filter(Customer_Customer.customer_phone_number.ilike(search)) + .all()) + + else: + customer_list = (db.session + .query(Customer_Customer) + .filter(Customer_Customer.customer_last_name.ilike(search)) + .all()) + + + customer_schema = Customer_Customer_schema(many=True) + return jsonify(customer_schema.dump(customer_list)) + + +@search.route("/delivery", methods=["GET"]) +def search_delivery(): + """ + pagination all customers + """ + keyword = request.args.get('q') + search = "%{}%".format(keyword) + search_type = (search[1]) + + delivery_ticket = (db.session + .query(Delivery_Delivery) + .filter(Delivery_Delivery.id.ilike(search)) + .all()) + + + delivery_schema = Delivery_Delivery_schema(many=True) + return jsonify(delivery_schema.dump(delivery_ticket)) \ No newline at end of file diff --git a/app/service/__init__.py b/app/service/__init__.py new file mode 100644 index 0000000..800ef82 --- /dev/null +++ b/app/service/__init__.py @@ -0,0 +1,7 @@ +# coding=utf-8 + +from flask import Blueprint + +service = Blueprint('service', __name__) + +from . import views \ No newline at end of file diff --git a/app/service/views.py b/app/service/views.py new file mode 100644 index 0000000..025943b --- /dev/null +++ b/app/service/views.py @@ -0,0 +1,397 @@ +from flask import request, jsonify +from flask_login import current_user, login_required +from app.service import service +from app import db +from datetime import datetime + +from app.classes.auth import Auth_User +from app.classes.customer import Customer_Customer +from app.classes.service import (Service_Call, + Service_Call_schema, + Service_Call_Notes_Dispatcher, + Service_Call_Notes_Technician, + Service_Call_Notes_Dispatcher_schema, + ) +from app.classes.cards import Card_Card +from app.classes.employee import Employee_Employee + + +@service.route("/", methods=["GET"]) +@login_required +def get_specific_service_call(service_id): + + service_call = db.session \ + .query(Service_Call) \ + .filter(Service_Call.id == service_id) \ + .first() + + service_schema = Service_Call_schema(many=False) + return jsonify(service_schema.dump(service_call)) + + +@service.route("/paymenttype//", methods=["PUT"]) +def update_a_service_payment(service_id, type_of_payment): + """ + This update a delivery for example if user updates to a fill + """ + + service_call = (db.session + .query(Service_Call) + .filter(Service_Call.id == service_id) + .first()) + + service_call.payment_type = type_of_payment + + db.session.add(service_call) + db.session.commit() + + return jsonify({"ok": True}), 200 + + +@service.route("/call/notes/", methods=["GET"]) +@login_required +def get_service_notes_call(service_id): + service_call = db.session \ + .query(Service_Call_Notes_Dispatcher) \ + .filter(Service_Call_Notes_Dispatcher.service_call_id == service_id) \ + .first() + + service_schema = Service_Call_Notes_Dispatcher_schema(many=False) + return jsonify(service_schema.dump(service_call)) + + +@service.route("/all", methods=["GET"]) +def service_view_all(): + """ + Get all service calls + """ + + service_calls = db.session \ + .query(Service_Call) \ + .filter(Service_Call.completed == 0) \ + .order_by(Service_Call.when_called.desc()) \ + .all() + + customer_schema = Service_Call_schema(many=True) + return jsonify(customer_schema.dump(service_calls)) + + +@service.route("/all/", methods=["GET"]) +def service_view(page): + """ + Get all service calls + """ + per_page_amount = 50 + if page is None: + offset_limit = 0 + elif page == 1: + offset_limit = 0 + else: + offset_limit = (per_page_amount * page) - per_page_amount + + service_calls = db.session \ + .query(Service_Call) \ + .filter(Service_Call.completed == 0) \ + .order_by(Service_Call.when_called.desc()) \ + .limit(per_page_amount).offset(offset_limit) + + customer_schema = Service_Call_schema(many=True) + return jsonify(customer_schema.dump(service_calls)) + + +@service.route("/customer//", methods=["GET"]) +def service_customer_view(customer_id, page): + """ + Get all service calls + """ + per_page_amount = 50 + if page is None: + offset_limit = 0 + elif page == 1: + offset_limit = 0 + else: + offset_limit = (per_page_amount * page) - per_page_amount + + service_calls = db.session \ + .query(Service_Call) \ + .filter(Service_Call.customer_id == customer_id) \ + .order_by(Service_Call.id.desc()) \ + .limit(per_page_amount).offset(offset_limit) + + customer_schema = Service_Call_schema(many=True) + return jsonify(customer_schema.dump(service_calls)) + + +@service.route("/create/", methods=["POST"]) +def service_create_call(user_id): + """ + create a service call + """ + + now = datetime.utcnow() + get_customer = db.session \ + .query(Customer_Customer) \ + .filter(Customer_Customer.id == user_id) \ + .first() + print(request.json) + get_service_type = request.json["type_of_service"] + service_note = request.json["dispatcher_notes_taken"] + service_subject = request.json["dispatcher_subject_taken"] + scheduled_date_date = request.json["date_scheduled"] + dispatcher_id = request.json["dispatcher_id"] + + card_payment = request.json["credit"] + cash_payment = request.json["cash"] + try: + if request.json["credit_card_id"]: + card_payment_id = request.json["credit_card_id"] + else: + card_payment_id = None + except: + card_payment_id = None + + if cash_payment is True and card_payment is False: + delivery_payment_method = 0 + elif card_payment is True and cash_payment is False: + delivery_payment_method = 1 + + elif card_payment is True and cash_payment is True: + delivery_payment_method = 2 + else: + delivery_payment_method = 3 + + if card_payment_id is not None: + get_card = (db.session + .query(Card_Card) + .filter(Card_Card.id == card_payment_id) + .filter(Card_Card.user_id == get_customer.id) + .first()) + card_id_from_customer = get_card.id + else: + card_id_from_customer = None + + date_object = datetime.strptime(scheduled_date_date, '%Y-%m-%d').date() + + get_tech = (db.session + .query(Employee_Employee) + .first()) + + create_a_call = Service_Call( + customer_id=get_customer.id, + customer_last_name=get_customer.customer_last_name, + customer_first_name=get_customer.customer_first_name, + customer_town=get_customer.customer_town, + customer_state=get_customer.customer_state, + customer_zip=get_customer.customer_zip, + customer_apt=get_customer.customer_apt, + customer_address=get_customer.customer_address, + status=0, + service_type=get_service_type, + when_called=now, + scheduled_date=date_object, + when_serviced=None, + tech_id=get_tech.id, + tech_first_name=get_tech.employee_first_name, + tech_last_name=get_tech.employee_last_name, + completed=0, + payment_type=delivery_payment_method, + payment_card_id=card_id_from_customer, + ) + + db.session.add(create_a_call) + db.session.flush() + + create_new_note = Service_Call_Notes_Dispatcher( + service_call_id=create_a_call.id, + dispatcher_subject=service_subject, + dispatcher_notes=service_note, + time_added=now, + dispatcher_id=dispatcher_id, + dispatcher_name=None, + ) + + db.session.add(create_new_note) + db.session.commit() + + db.session.commit() + + return jsonify({"ok": True, + 'user_id': get_customer.id, + 'service_id': create_a_call.id, + }), 200 + +@service.route("/delete/", methods=["DELETE"]) +def service_delete_call(service_id): + """ + delete a service call + """ + get_call_to_delete = (db.session + .query(Service_Call) + .filter(Service_Call.id == service_id) + .first()) + db.session.delete(get_call_to_delete) + db.session.commit() + + return jsonify({"ok": True}), 200 + + + +@service.route("/edit/", methods=["PUT"]) +def service_edit_call(service_id): + """ + Update a service call + """ + + get_service_type = request.json["type_of_service"] + scheduled_date_date = request.json["date_scheduled"] + dispatcher_subject_taken = request.json["dispatcher_subject_taken"] + dispatcher_notes_taken = request.json["dispatcher_notes_taken"] + tech_id = request.json["tech_id"] + + card_payment = request.json["credit"] + cash_payment = request.json["cash"] + + if request.json["credit_card_id"]: + card_payment_id = request.json["credit_card_id"] + else: + card_payment_id = None + + get_tech = db.session \ + .query(Employee_Employee) \ + .filter(Employee_Employee.id == tech_id) \ + .first() + + get_service_call_call = db.session \ + .query(Service_Call) \ + .filter(Service_Call.id == service_id) \ + .first() + + if card_payment_id is not None: + get_customer = db.session \ + .query(Customer_Customer) \ + .filter(Customer_Customer.id == get_service_call_call.customer_id) \ + .first() + + get_card = (db.session + .query(Card_Card) + .filter(Card_Card.id == card_payment_id) + .filter(Card_Card.user_id == get_customer.id) + .first()) + card_id_from_customer = get_card.id + else: + card_id_from_customer = None + + if cash_payment is True and card_payment is False: + delivery_payment_method = 0 + elif card_payment is True and cash_payment is False: + delivery_payment_method = 1 + + elif card_payment is True and cash_payment is True: + delivery_payment_method = 2 + else: + delivery_payment_method = 3 + + get_service_call_notes = (db.session + .query(Service_Call_Notes_Dispatcher) + .filter(Service_Call_Notes_Dispatcher.service_call_id == get_service_call_call.id) + .first()) + + get_service_call_notes.dispatcher_subject = dispatcher_subject_taken + get_service_call_notes.dispatcher_notes = dispatcher_notes_taken + + get_service_call_call.service_type = get_service_type + get_service_call_call.scheduled_date = scheduled_date_date + get_service_call_call.tech_id = get_tech.id + get_service_call_call.payment_type = delivery_payment_method + get_service_call_call.payment_card_id = card_id_from_customer + + db.session.add(get_service_call_call) + db.session.commit() + + return jsonify({"ok": True}), 200 + + +@service.route("/update/type/", methods=["PUT"]) +def service_update_service_type(service_id): + """ + Update a service call diagnosis + """ + get_service_type = request.json["service_type"] + + get_service_call = db.session \ + .query(Service_Call) \ + .filter(Service_Call.service_id == service_id) \ + .first() + + get_service_call.service_type = get_service_type + + db.session.add(get_service_call) + db.session.commit() + + return jsonify({"ok": True}), 200 + + +@service.route("/note/dispatcher/", methods=["PUT"]) +def service_create_note_dispatcher(service_id): + """ + Initial dispatcher note about the call + """ + + service_note = request.json["dispatcher_text"] + now = datetime.utcnow() + + user = db.session \ + .query(Auth_User) \ + .filter(Auth_User.id == current_user.id) \ + .first() + + get_service_call_order = db.session \ + .query(Service_Call) \ + .filter(Service_Call.service_id == service_id) \ + .first() + + create_new_note = Service_Call_Notes_Dispatcher( + service_call_id=get_service_call_order.id, + dispatcher_notes=service_note, + time_added=now, + dispatcher_id=user.id, + dispatcher_name=user.username, + ) + + db.session.add(create_new_note) + db.session.commit() + + return jsonify({"ok": True}), 200 + + +@service.route("/note/technician/", methods=["PUT"]) +def service_create_note_technician(service_id): + """ + Technician can create notes on the call + """ + + service_technician_notes = request.json["technician_comments"] + now = datetime.utcnow() + + user = db.session \ + .query(Auth_User) \ + .filter(Auth_User.id == current_user.id) \ + .first() + + get_service_call = db.session \ + .query(Service_Call) \ + .filter(Service_Call.service_id == service_id) \ + .first() + + create_new_note = Service_Call_Notes_Technician( + service_call_id=get_service_call.id, + technician_comments=service_technician_notes, + time_added=now, + technician_id=user.id, + technician_name=user.username, + ) + + db.session.add(create_new_note) + db.session.commit() + + return jsonify({"ok": True}), 200 diff --git a/app/stats/__init__.py b/app/stats/__init__.py new file mode 100644 index 0000000..19ea078 --- /dev/null +++ b/app/stats/__init__.py @@ -0,0 +1,7 @@ +# coding=utf-8 + +from flask import Blueprint + +stats = Blueprint('stats', __name__) + +from . import views \ No newline at end of file diff --git a/app/stats/views.py b/app/stats/views.py new file mode 100644 index 0000000..72091ff --- /dev/null +++ b/app/stats/views.py @@ -0,0 +1,31 @@ +from flask import jsonify +from sqlalchemy import func +from datetime import date +from app.stats import stats +from app import db +from app.classes.delivery import Delivery_Delivery +from app.classes.service import Service_Call + + +@stats.route("/delivery/count/today", methods=["GET"]) +def get_delivery_today(): + today_deliveries = (db.session + .query(Delivery_Delivery) + .order_by(func.date(Delivery_Delivery.expected_delivery_date) == date.today()) + .count()) + + return jsonify({"ok": True, + 'data': today_deliveries, + }), 200 + + +@stats.route("/service/count/today", methods=["GET"]) +def get_service_today(): + today_calls = (db.session + .query(Service_Call) + .order_by(func.date(Service_Call.scheduled_date) == date.today()) + .count()) + + return jsonify({"ok": True, + 'data': today_calls, + }), 200 diff --git a/requirements.txt b/requirements.txt new file mode 100755 index 0000000..c6153d3 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,19 @@ +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 \ No newline at end of file