diff --git a/.gitignore b/.gitignore index 5eb4483f..97b05c0d 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ __pycache__/ node_modules /pyrightconfig.json /tests/files/tickets.csv +/log/*.log diff --git a/log/.keep b/log/.keep new file mode 100644 index 00000000..e69de29b diff --git a/migrations/versions/c09e95d03bac_.py b/migrations/versions/47bf06847903_.py similarity index 82% rename from migrations/versions/c09e95d03bac_.py rename to migrations/versions/47bf06847903_.py index 58a7eece..61520204 100644 --- a/migrations/versions/c09e95d03bac_.py +++ b/migrations/versions/47bf06847903_.py @@ -1,8 +1,8 @@ """empty message -Revision ID: c09e95d03bac +Revision ID: 47bf06847903 Revises: -Create Date: 2022-06-21 10:41:50.430102 +Create Date: 2022-06-21 12:19:38.184089 """ from alembic import op @@ -10,7 +10,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = 'c09e95d03bac' +revision = '47bf06847903' down_revision = None branch_labels = None depends_on = None @@ -57,7 +57,7 @@ def upgrade(): sa.Column('bpmn_json', sa.JSON(), nullable=True), sa.Column('start_in_seconds', sa.Integer(), nullable=True), sa.Column('end_in_seconds', sa.Integer(), nullable=True), - sa.Column('last_updated', sa.DateTime(timezone=True), nullable=True), + sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), sa.Column('process_initiator_id', sa.Integer(), nullable=False), sa.Column('status', sa.Enum('not_started', 'user_input_required', 'waiting', 'complete', 'erroring', name='processinstancestatus'), nullable=True), sa.ForeignKeyConstraint(['process_initiator_id'], ['user.id'], ), @@ -65,6 +65,19 @@ def upgrade(): ) op.create_index(op.f('ix_process_instance_process_group_identifier'), 'process_instance', ['process_group_identifier'], unique=False) op.create_index(op.f('ix_process_instance_process_model_identifier'), 'process_instance', ['process_model_identifier'], unique=False) + op.create_table('process_instance_report', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('process_model_identifier', sa.String(length=50), nullable=False), + sa.Column('process_group_identifier', sa.String(length=50), nullable=False), + sa.Column('report_json', sa.JSON(), nullable=True), + sa.Column('created_by_id', sa.Integer(), nullable=False), + sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True), + sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True), + sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index(op.f('ix_process_instance_report_process_group_identifier'), 'process_instance_report', ['process_group_identifier'], unique=False) + op.create_index(op.f('ix_process_instance_report_process_model_identifier'), 'process_instance_report', ['process_model_identifier'], unique=False) op.create_table('user_group_assignment', sa.Column('id', sa.Integer(), nullable=False), sa.Column('user_id', sa.Integer(), nullable=False), @@ -136,6 +149,9 @@ def downgrade(): op.drop_table('task_event') op.drop_table('file') op.drop_table('user_group_assignment') + op.drop_index(op.f('ix_process_instance_report_process_model_identifier'), table_name='process_instance_report') + op.drop_index(op.f('ix_process_instance_report_process_group_identifier'), table_name='process_instance_report') + op.drop_table('process_instance_report') op.drop_index(op.f('ix_process_instance_process_model_identifier'), table_name='process_instance') op.drop_index(op.f('ix_process_instance_process_group_identifier'), table_name='process_instance') op.drop_table('process_instance') diff --git a/src/spiffworkflow_backend/config/__init__.py b/src/spiffworkflow_backend/config/__init__.py index 3e7d9c84..f063c397 100644 --- a/src/spiffworkflow_backend/config/__init__.py +++ b/src/spiffworkflow_backend/config/__init__.py @@ -1,21 +1,24 @@ """__init__.py.""" import os +import logging from flask.app import Flask from werkzeug.utils import ImportStringError -def setup_config(app: Flask) -> None: - """Setup_config.""" - # ensure the instance folder exists - try: - os.makedirs(app.instance_path) - except OSError: - pass +def setup_logger_for_sql_statements(app: Flask): + db_log_file_name = f'log/db_{app.env}.log' + db_handler_log_level = logging.INFO + db_logger_log_level = logging.DEBUG + db_handler = logging.FileHandler(db_log_file_name) + db_handler.setLevel(db_handler_log_level) + db_logger = logging.getLogger('sqlalchemy') + db_logger.propagate = False + db_logger.addHandler(db_handler) + db_logger.setLevel(db_logger_log_level) - app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False - app.config.from_object("spiffworkflow_backend.config.default") +def setup_database_uri(app: Flask): if os.environ.get("DATABASE_URI") is None: if os.environ.get("SPIFF_DATABASE_TYPE") == "sqlite": app.config[ @@ -36,6 +39,21 @@ def setup_config(app: Flask) -> None: else: app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get("DATABASE_URI") + +def setup_config(app: Flask) -> None: + """Setup_config.""" + # ensure the instance folder exists + try: + os.makedirs(app.instance_path) + except OSError: + pass + + app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False + app.config.from_object("spiffworkflow_backend.config.default") + + setup_database_uri(app) + setup_logger_for_sql_statements(app) + env_config_module = "spiffworkflow_backend.config." + app.env try: app.config.from_object(env_config_module) diff --git a/src/spiffworkflow_backend/load_database_models.py b/src/spiffworkflow_backend/load_database_models.py index a5c605a2..e298106d 100644 --- a/src/spiffworkflow_backend/load_database_models.py +++ b/src/spiffworkflow_backend/load_database_models.py @@ -4,8 +4,8 @@ from flask_bpmn.models.db import add_listeners # type: ignore from spiffworkflow_backend.models.data_store import DataStoreModel from spiffworkflow_backend.models.file import FileModel -from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel -from spiffworkflow_backend.models.permission_target import PermissionTargetModel +# from spiffworkflow_backend.models.permission_assignment import PermissionAssignmentModel +# from spiffworkflow_backend.models.permission_target import PermissionTargetModel from spiffworkflow_backend.models.principal import PrincipalModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance_report import ProcessInstanceReportModel diff --git a/src/spiffworkflow_backend/models/process_instance.py b/src/spiffworkflow_backend/models/process_instance.py index d3b7ecea..fd9a68a5 100644 --- a/src/spiffworkflow_backend/models/process_instance.py +++ b/src/spiffworkflow_backend/models/process_instance.py @@ -82,7 +82,7 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel): # type: ignore bpmn_json = deferred(db.Column(db.JSON)) start_in_seconds = db.Column(db.Integer) end_in_seconds = db.Column(db.Integer) - last_updated = db.Column(db.DateTime(timezone=True)) + updated_at_in_seconds = db.Column(db.Integer) process_initiator_id = db.Column(ForeignKey(UserModel.id), nullable=False) process_initiator = relationship("UserModel") status = db.Column(db.Enum(ProcessInstanceStatus)) @@ -114,7 +114,7 @@ class ProcessInstanceApi: process_group_identifier, total_tasks, completed_tasks, - last_updated, + updated_at_in_seconds, is_review, title, ): @@ -127,7 +127,7 @@ class ProcessInstanceApi: self.process_group_identifier = process_group_identifier self.total_tasks = total_tasks self.completed_tasks = completed_tasks - self.last_updated = last_updated + self.updated_at_in_seconds = updated_at_in_seconds self.title = title self.is_review = is_review @@ -148,7 +148,7 @@ class ProcessInstanceApiSchema(Schema): "process_group_identifier", "total_tasks", "completed_tasks", - "last_updated", + "updated_at_in_seconds", "is_review", "title", "study_id", @@ -175,7 +175,7 @@ class ProcessInstanceApiSchema(Schema): "process_group_identifier", "total_tasks", "completed_tasks", - "last_updated", + "updated_at_in_seconds", "is_review", "title", "study_id",