From 3cd7ff11f6dac9190230a8d8170e6eda640ab1eb Mon Sep 17 00:00:00 2001 From: tanshu Date: Sun, 10 May 2020 20:36:19 +0530 Subject: [PATCH] Added Alembic Breaking: Changed a lot of column names --- .env | 6 +- alembic.ini | 85 +++ alembic/README | 1 + alembic/env.py | 86 +++ alembic/script.py.mako | 24 + .../versions/0bf3d70ee7de_initial_commit.py | 314 ++++++++++ alembic/versions/eed0b382c287_my_test.py | 538 ++++++++++++++++++ bc2f5ea0c0d7_my_test.py | 378 ++++++++++++ brewman/__init__.py | 3 - brewman/config.py | 2 +- brewman/core/security.py | 20 +- brewman/db/base.py | 2 +- brewman/main.py | 5 +- brewman/models/__init__.py | 78 +-- brewman/models/auth.py | 74 +-- brewman/models/master.py | 61 +- brewman/models/voucher.py | 114 ++-- brewman/routers/account.py | 21 +- brewman/routers/account_types.py | 5 +- brewman/routers/attendance.py | 5 +- brewman/routers/auth/group.py | 93 --- brewman/routers/auth/role.py | 163 ++++++ brewman/routers/auth/user.py | 357 +++++++----- brewman/routers/cost_centre.py | 15 +- brewman/routers/employee.py | 19 +- brewman/routers/product.py | 19 +- brewman/routers/product_group.py | 15 +- brewman/schemas/auth.py | 87 ++- brewman/subscribers.py | 17 - requirements.txt | 4 +- 30 files changed, 2050 insertions(+), 561 deletions(-) create mode 100644 alembic.ini create mode 100644 alembic/README create mode 100644 alembic/env.py create mode 100644 alembic/script.py.mako create mode 100644 alembic/versions/0bf3d70ee7de_initial_commit.py create mode 100644 alembic/versions/eed0b382c287_my_test.py create mode 100644 bc2f5ea0c0d7_my_test.py delete mode 100644 brewman/routers/auth/group.py create mode 100644 brewman/routers/auth/role.py delete mode 100644 brewman/subscribers.py diff --git a/.env b/.env index e6288ca8..cfc6b753 100644 --- a/.env +++ b/.env @@ -6,4 +6,8 @@ DB_URL=postgresql://postgres:123456@localhost:5432/hops MODULE_NAME=brewman.main SERVER_NAME=localhost SERVER_HOST=localhost -PROJECT_NAME=bifrost \ No newline at end of file +PROJECT_NAME=bifrost +POSTGRES_SERVER=localhost +POSTGRES_USER=postgres +POSTGRES_PASSWORD=123456 +POSTGRES_DB=hops diff --git a/alembic.ini b/alembic.ini new file mode 100644 index 00000000..3774c9cc --- /dev/null +++ b/alembic.ini @@ -0,0 +1,85 @@ +# A generic, single database configuration. + +[alembic] +# path to migration scripts +script_location = alembic + +# template used to generate migration files +# file_template = %%(rev)s_%%(slug)s + +# timezone to use when rendering the date +# within the migration file as well as the filename. +# string value is passed to dateutil.tz.gettz() +# leave blank for localtime +# timezone = + +# max length of characters to apply to the +# "slug" field +# truncate_slug_length = 40 + +# set to 'true' to run the environment during +# the 'revision' command, regardless of autogenerate +# revision_environment = false + +# set to 'true' to allow .pyc and .pyo files without +# a source .py file to be detected as revisions in the +# versions/ directory +# sourceless = false + +# version location specification; this defaults +# to alembic/versions. When using multiple version +# directories, initial revisions must be specified with --version-path +# version_locations = %(here)s/bar %(here)s/bat alembic/versions + +# the output encoding used when revision files +# are written from script.py.mako +# output_encoding = utf-8 + +sqlalchemy.url = postgresql://postgres:123456@localhost:5432/hops + + +[post_write_hooks] +# post_write_hooks defines scripts or Python functions that are run +# on newly generated revision scripts. See the documentation for further +# detail and examples + +# format using "black" - use the console_scripts runner, against the "black" entrypoint +# hooks=black +# black.type=console_scripts +# black.entrypoint=black +# black.options=-l 79 + +# Logging configuration +[loggers] +keys = root,sqlalchemy,alembic + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/alembic/README b/alembic/README new file mode 100644 index 00000000..98e4f9c4 --- /dev/null +++ b/alembic/README @@ -0,0 +1 @@ +Generic single-database configuration. \ No newline at end of file diff --git a/alembic/env.py b/alembic/env.py new file mode 100644 index 00000000..7d4a5ce4 --- /dev/null +++ b/alembic/env.py @@ -0,0 +1,86 @@ +import os +from logging.config import fileConfig + +from sqlalchemy import engine_from_config +from sqlalchemy import pool + +from alembic import context + +# this is the Alembic Config object, which provides +# access to the values within the .ini file in use. +config = context.config + +# Interpret the config file for Python logging. +# This line sets up loggers basically. +fileConfig(config.config_file_name) + +from brewman.models.auth import User # noqa +target_metadata = User.metadata +print(target_metadata) + +# other values from the config, defined by the needs of env.py, +# can be acquired: +# my_important_option = config.get_main_option("my_important_option") +# ... etc. + + +def get_url(): + user = os.getenv("POSTGRES_USER", "postgres") + password = os.getenv("POSTGRES_PASSWORD", "123456") + server = os.getenv("POSTGRES_SERVER", "localhost") + db = os.getenv("POSTGRES_DB", "hops") + return f"postgresql://{user}:{password}@{server}/{db}" + + +def run_migrations_offline(): + """Run migrations in 'offline' mode. + + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. + + Calls to context.execute() here emit the given string to the + script output. + + """ + url = get_url() + context.configure( + url=url, + target_metadata=target_metadata, + literal_binds=True, + dialect_opts={"paramstyle": "named"}, + ) + + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online(): + """Run migrations in 'online' mode. + + In this scenario we need to create an Engine + and associate a connection with the context. + + """ + configuration = config.get_section(config.config_ini_section) + configuration["sqlalchemy.url"] = get_url() + connectable = engine_from_config( + config.get_section(config.config_ini_section), + prefix="sqlalchemy.", + poolclass=pool.NullPool, + ) + + with connectable.connect() as connection: + context.configure( + connection=connection, target_metadata=target_metadata + ) + + with context.begin_transaction(): + context.run_migrations() + + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/alembic/script.py.mako b/alembic/script.py.mako new file mode 100644 index 00000000..2c015630 --- /dev/null +++ b/alembic/script.py.mako @@ -0,0 +1,24 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} + +""" +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} +branch_labels = ${repr(branch_labels)} +depends_on = ${repr(depends_on)} + + +def upgrade(): + ${upgrades if upgrades else "pass"} + + +def downgrade(): + ${downgrades if downgrades else "pass"} diff --git a/alembic/versions/0bf3d70ee7de_initial_commit.py b/alembic/versions/0bf3d70ee7de_initial_commit.py new file mode 100644 index 00000000..22df82de --- /dev/null +++ b/alembic/versions/0bf3d70ee7de_initial_commit.py @@ -0,0 +1,314 @@ +"""Initial Commit + +Revision ID: 0bf3d70ee7de +Revises: +Create Date: 2020-05-10 19:02:57.301086 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '0bf3d70ee7de' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('auth_clients', + sa.Column('client_id', postgresql.UUID(), nullable=False), + sa.Column('code', sa.Integer(), nullable=False), + sa.Column('name', sa.Unicode(length=255), nullable=False), + sa.Column('enabled', sa.Boolean(), nullable=False), + sa.Column('otp', sa.Integer(), nullable=True), + sa.Column('creation_date', sa.DateTime(timezone=True), nullable=False), + sa.PrimaryKeyConstraint('client_id', name=op.f('pk_auth_clients')), + sa.UniqueConstraint('code', name=op.f('uq_auth_clients_code')), + sa.UniqueConstraint('name', name=op.f('uq_auth_clients_name')) + ) + op.create_table('auth_groups', + sa.Column('GroupID', postgresql.UUID(), nullable=False), + sa.Column('Name', sa.Unicode(length=255), nullable=True), + sa.PrimaryKeyConstraint('GroupID', name=op.f('pk_auth_groups')), + sa.UniqueConstraint('Name', name=op.f('uq_auth_groups_Name')) + ) + op.create_table('auth_roles', + sa.Column('RoleID', postgresql.UUID(), nullable=False), + sa.Column('Name', sa.Unicode(length=255), nullable=True), + sa.PrimaryKeyConstraint('RoleID', name=op.f('pk_auth_roles')), + sa.UniqueConstraint('Name', name=op.f('uq_auth_roles_Name')) + ) + op.create_table('auth_users', + sa.Column('UserID', postgresql.UUID(), nullable=False), + sa.Column('Name', sa.Unicode(length=255), nullable=True), + sa.Column('Password', sa.Unicode(length=60), nullable=True), + sa.Column('LockedOut', sa.Boolean(), nullable=True), + sa.PrimaryKeyConstraint('UserID', name=op.f('pk_auth_users')), + sa.UniqueConstraint('Name', name=op.f('uq_auth_users_Name')) + ) + op.create_table('cost_centres', + sa.Column('CostCentreID', postgresql.UUID(), nullable=False), + sa.Column('Name', sa.Unicode(length=255), nullable=True), + sa.Column('IsFixture', sa.Boolean(), nullable=False), + sa.PrimaryKeyConstraint('CostCentreID', name=op.f('pk_cost_centres')), + sa.UniqueConstraint('Name', name=op.f('uq_cost_centres_Name')) + ) + op.create_table('images', + sa.Column('id', postgresql.UUID(), nullable=False), + sa.Column('resource_id', postgresql.UUID(), nullable=False), + sa.Column('resource_type', sa.Unicode(length=255), nullable=False), + sa.Column('image', postgresql.BYTEA(), nullable=False), + sa.Column('thumbnail', postgresql.BYTEA(), nullable=False), + sa.Column('creation_date', sa.DateTime(timezone=True), nullable=False), + sa.PrimaryKeyConstraint('id', name=op.f('pk_images')) + ) + op.create_table('product_groups', + sa.Column('ProductGroupID', postgresql.UUID(), nullable=False), + sa.Column('Name', sa.Unicode(length=255), nullable=True), + sa.Column('IsFixture', sa.Boolean(), nullable=False), + sa.PrimaryKeyConstraint('ProductGroupID', name=op.f('pk_product_groups')), + sa.UniqueConstraint('Name', name=op.f('uq_product_groups_Name')) + ) + op.create_table('settings', + sa.Column('SettingID', postgresql.UUID(), nullable=False), + sa.Column('Name', sa.Unicode(length=255), nullable=False), + sa.Column('Data', sa.PickleType(), nullable=True), + sa.PrimaryKeyConstraint('SettingID', name=op.f('pk_settings')), + sa.UniqueConstraint('Name', name=op.f('uq_settings_Name')) + ) + op.create_table('accounts', + sa.Column('id', postgresql.UUID(), nullable=False), + sa.Column('code', sa.Integer(), nullable=False), + sa.Column('name', sa.Unicode(length=255), nullable=False), + sa.Column('type', sa.Integer(), nullable=False), + sa.Column('account_type', sa.Unicode(length=50), nullable=False), + sa.Column('is_starred', sa.Boolean(), nullable=False), + sa.Column('is_active', sa.Boolean(), nullable=False), + sa.Column('is_reconcilable', sa.Boolean(), nullable=False), + sa.Column('cost_centre_id', postgresql.UUID(), nullable=False), + sa.Column('is_fixture', sa.Boolean(), nullable=False), + sa.ForeignKeyConstraint(['cost_centre_id'], ['cost_centres.CostCentreID'], name=op.f('fk_accounts_cost_centre_id_cost_centres')), + sa.PrimaryKeyConstraint('id', name=op.f('pk_accounts')), + sa.UniqueConstraint('name', name=op.f('uq_accounts_name')) + ) + op.create_table('auth_login_history', + sa.Column('login_history_id', postgresql.UUID(), nullable=False), + sa.Column('user_id', postgresql.UUID(), nullable=False), + sa.Column('client_id', postgresql.UUID(), nullable=False), + sa.Column('date', sa.DateTime(timezone=True), nullable=False), + sa.ForeignKeyConstraint(['client_id'], ['auth_clients.client_id'], name=op.f('fk_auth_login_history_client_id_auth_clients')), + sa.ForeignKeyConstraint(['user_id'], ['auth_users.UserID'], name=op.f('fk_auth_login_history_user_id_auth_users')), + sa.PrimaryKeyConstraint('login_history_id', name=op.f('pk_auth_login_history')), + sa.UniqueConstraint('user_id', 'client_id', 'date', name=op.f('uq_auth_login_history_user_id')) + ) + op.create_table('auth_rolegroups', + sa.Column('RoleGroupID', postgresql.UUID(), nullable=False), + sa.Column('RoleID', postgresql.UUID(), nullable=True), + sa.Column('GroupID', postgresql.UUID(), nullable=True), + sa.ForeignKeyConstraint(['GroupID'], ['auth_groups.GroupID'], name=op.f('fk_auth_rolegroups_GroupID_auth_groups')), + sa.ForeignKeyConstraint(['RoleID'], ['auth_roles.RoleID'], name=op.f('fk_auth_rolegroups_RoleID_auth_roles')), + sa.PrimaryKeyConstraint('RoleGroupID', name=op.f('pk_auth_rolegroups')) + ) + op.create_table('auth_usergroups', + sa.Column('UserGroupID', postgresql.UUID(), nullable=False), + sa.Column('UserID', postgresql.UUID(), nullable=True), + sa.Column('GroupID', postgresql.UUID(), nullable=True), + sa.ForeignKeyConstraint(['GroupID'], ['auth_groups.GroupID'], name=op.f('fk_auth_usergroups_GroupID_auth_groups')), + sa.ForeignKeyConstraint(['UserID'], ['auth_users.UserID'], name=op.f('fk_auth_usergroups_UserID_auth_users')), + sa.PrimaryKeyConstraint('UserGroupID', name=op.f('pk_auth_usergroups')) + ) + op.create_table('vouchers', + sa.Column('VoucherID', postgresql.UUID(), nullable=False), + sa.Column('date', sa.DateTime(), nullable=False), + sa.Column('narration', sa.Unicode(length=1000), nullable=False), + sa.Column('is_reconciled', sa.Boolean(), nullable=False), + sa.Column('reconcile_date', sa.DateTime(), nullable=False), + sa.Column('is_starred', sa.Boolean(), nullable=False), + sa.Column('creation_date', sa.DateTime(timezone=True), nullable=False), + sa.Column('last_edit_date', sa.DateTime(timezone=True), nullable=False), + sa.Column('voucher_type', sa.Integer(), nullable=False), + sa.Column('user_id', postgresql.UUID(), nullable=False), + sa.Column('is_posted', sa.Boolean(), nullable=False), + sa.Column('poster_id', postgresql.UUID(), nullable=True), + sa.ForeignKeyConstraint(['poster_id'], ['auth_users.UserID'], name=op.f('fk_vouchers_poster_id_auth_users')), + sa.ForeignKeyConstraint(['user_id'], ['auth_users.UserID'], name=op.f('fk_vouchers_user_id_auth_users')), + sa.PrimaryKeyConstraint('VoucherID', name=op.f('pk_vouchers')) + ) + op.create_index(op.f('ix_vouchers_date'), 'vouchers', ['date'], unique=False) + op.create_table('employees', + sa.Column('id', postgresql.UUID(), nullable=False), + sa.Column('Designation', sa.Unicode(length=255), nullable=True), + sa.Column('Salary', sa.Integer(), nullable=True), + sa.Column('ServicePoints', sa.Numeric(precision=5, scale=2), nullable=True), + sa.Column('JoiningDate', sa.DateTime(), nullable=True), + sa.Column('LeavingDate', sa.DateTime(), nullable=True), + sa.ForeignKeyConstraint(['id'], ['accounts.id'], name=op.f('fk_employees_id_accounts')), + sa.PrimaryKeyConstraint('id', name=op.f('pk_employees')) + ) + op.create_table('journals', + sa.Column('JournalID', postgresql.UUID(), nullable=False), + sa.Column('Debit', sa.Integer(), nullable=True), + sa.Column('Amount', sa.Numeric(), nullable=True), + sa.Column('VoucherID', postgresql.UUID(), nullable=False), + sa.Column('account_id', postgresql.UUID(), nullable=False), + sa.Column('CostCentreID', postgresql.UUID(), nullable=False), + sa.ForeignKeyConstraint(['CostCentreID'], ['cost_centres.CostCentreID'], name=op.f('fk_journals_CostCentreID_cost_centres')), + sa.ForeignKeyConstraint(['VoucherID'], ['vouchers.VoucherID'], name=op.f('fk_journals_VoucherID_vouchers')), + sa.ForeignKeyConstraint(['account_id'], ['accounts.id'], name=op.f('fk_journals_account_id_accounts')), + sa.PrimaryKeyConstraint('JournalID', name=op.f('pk_journals')) + ) + op.create_index(op.f('ix_journals_VoucherID'), 'journals', ['VoucherID'], unique=False) + op.create_table('products', + sa.Column('ProductID', postgresql.UUID(), nullable=False), + sa.Column('Code', sa.Integer(), nullable=True), + sa.Column('Name', sa.Unicode(length=255), nullable=False), + sa.Column('Units', sa.Unicode(length=255), nullable=False), + sa.Column('Fraction', sa.Numeric(), nullable=False), + sa.Column('FractionUnits', sa.Unicode(length=255), nullable=False), + sa.Column('ProductYield', sa.Numeric(), nullable=False), + sa.Column('ProductGroupID', postgresql.UUID(), nullable=False), + sa.Column('account_id', postgresql.UUID(), nullable=False), + sa.Column('cost_price', sa.Numeric(), nullable=False), + sa.Column('sale_price', sa.Numeric(), nullable=False), + sa.Column('IsActive', sa.Boolean(), nullable=False), + sa.Column('IsFixture', sa.Boolean(), nullable=False), + sa.Column('is_purchased', sa.Boolean(), nullable=False), + sa.Column('is_sold', sa.Boolean(), nullable=False), + sa.ForeignKeyConstraint(['ProductGroupID'], ['product_groups.ProductGroupID'], name=op.f('fk_products_ProductGroupID_product_groups')), + sa.ForeignKeyConstraint(['account_id'], ['accounts.id'], name=op.f('fk_products_account_id_accounts')), + sa.PrimaryKeyConstraint('ProductID', name=op.f('pk_products')), + sa.UniqueConstraint('Code', name=op.f('uq_products_Code')), + sa.UniqueConstraint('Name', 'Units', name=op.f('uq_products_Name')) + ) + op.create_table('attendances', + sa.Column('AttendanceID', postgresql.UUID(), nullable=False), + sa.Column('EmployeeID', postgresql.UUID(), nullable=True), + sa.Column('Date', sa.DateTime(), nullable=True), + sa.Column('AttendanceType', sa.Integer(), nullable=True), + sa.Column('Amount', sa.Numeric(), nullable=True), + sa.Column('CreationDate', sa.DateTime(timezone=True), nullable=True), + sa.Column('UserID', postgresql.UUID(), nullable=True), + sa.Column('IsValid', sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint(['EmployeeID'], ['employees.id'], name=op.f('fk_attendances_EmployeeID_employees')), + sa.ForeignKeyConstraint(['UserID'], ['auth_users.UserID'], name=op.f('fk_attendances_UserID_auth_users')), + sa.PrimaryKeyConstraint('AttendanceID', name=op.f('pk_attendances')) + ) + op.create_table('batches', + sa.Column('BatchID', postgresql.UUID(), nullable=False), + sa.Column('Name', sa.DateTime(), nullable=True), + sa.Column('ProductID', postgresql.UUID(), nullable=False), + sa.Column('QuantityRemaining', sa.Numeric(), nullable=True), + sa.Column('Rate', sa.Numeric(), nullable=True), + sa.Column('Tax', sa.Numeric(), nullable=True), + sa.Column('Discount', sa.Numeric(), nullable=True), + sa.ForeignKeyConstraint(['ProductID'], ['products.ProductID'], name=op.f('fk_batches_ProductID_products')), + sa.PrimaryKeyConstraint('BatchID', name=op.f('pk_batches')) + ) + op.create_table('fingerprints', + sa.Column('FingerprintID', postgresql.UUID(), nullable=False), + sa.Column('EmployeeID', postgresql.UUID(), nullable=True), + sa.Column('Date', sa.DateTime(), nullable=True), + sa.ForeignKeyConstraint(['EmployeeID'], ['employees.id'], name=op.f('fk_fingerprints_EmployeeID_employees')), + sa.PrimaryKeyConstraint('FingerprintID', name=op.f('pk_fingerprints')) + ) + op.create_table('recipes', + sa.Column('recipe_id', postgresql.UUID(), nullable=False), + sa.Column('product_id', postgresql.UUID(), nullable=False), + sa.Column('quantity', sa.Numeric(), nullable=False), + sa.Column('cost_price', sa.Numeric(), nullable=False), + sa.Column('sale_price', sa.Numeric(), nullable=False), + sa.Column('notes', sa.Unicode(length=255), nullable=True), + sa.Column('valid_from', sa.Date(), nullable=False), + sa.Column('valid_to', sa.Date(), nullable=False), + sa.Column('effective_from', sa.Date(), nullable=False), + sa.Column('effective_to', sa.Date(), nullable=True), + sa.ForeignKeyConstraint(['product_id'], ['products.ProductID'], name=op.f('fk_recipes_product_id_products')), + sa.PrimaryKeyConstraint('recipe_id', name=op.f('pk_recipes')) + ) + op.create_table('salary_deductions', + sa.Column('SalaryDeductionID', postgresql.UUID(), nullable=False), + sa.Column('VoucherID', postgresql.UUID(), nullable=False), + sa.Column('JournalID', postgresql.UUID(), nullable=False), + sa.Column('GrossSalary', sa.Integer(), nullable=True), + sa.Column('DaysWorked', sa.Integer(), nullable=True), + sa.Column('EsiEmployee', sa.Integer(), nullable=True), + sa.Column('PfEmployee', sa.Integer(), nullable=True), + sa.Column('EsiEmployer', sa.Integer(), nullable=True), + sa.Column('PfEmployer', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['JournalID'], ['journals.JournalID'], name=op.f('fk_salary_deductions_JournalID_journals')), + sa.ForeignKeyConstraint(['VoucherID'], ['vouchers.VoucherID'], name=op.f('fk_salary_deductions_VoucherID_vouchers')), + sa.PrimaryKeyConstraint('SalaryDeductionID', name=op.f('pk_salary_deductions')) + ) + op.create_table('service_charges', + sa.Column('id', postgresql.UUID(), nullable=False), + sa.Column('voucher_id', postgresql.UUID(), nullable=False), + sa.Column('journal_id', postgresql.UUID(), nullable=False), + sa.Column('days_worked', sa.Integer(), nullable=False), + sa.Column('points', sa.Numeric(precision=5, scale=2), nullable=False), + sa.ForeignKeyConstraint(['journal_id'], ['journals.JournalID'], name=op.f('fk_service_charges_journal_id_journals')), + sa.ForeignKeyConstraint(['voucher_id'], ['vouchers.VoucherID'], name=op.f('fk_service_charges_voucher_id_vouchers')), + sa.PrimaryKeyConstraint('id', name=op.f('pk_service_charges')) + ) + op.create_table('inventories', + sa.Column('InventoryID', postgresql.UUID(), nullable=False), + sa.Column('VoucherID', postgresql.UUID(), nullable=False), + sa.Column('ProductID', postgresql.UUID(), nullable=False), + sa.Column('BatchID', postgresql.UUID(), nullable=False), + sa.Column('Quantity', sa.Numeric(), nullable=True), + sa.Column('Rate', sa.Numeric(), nullable=True), + sa.Column('Tax', sa.Numeric(), nullable=True), + sa.Column('Discount', sa.Numeric(), nullable=True), + sa.ForeignKeyConstraint(['BatchID'], ['batches.BatchID'], name=op.f('fk_inventories_BatchID_batches')), + sa.ForeignKeyConstraint(['ProductID'], ['products.ProductID'], name=op.f('fk_inventories_ProductID_products')), + sa.ForeignKeyConstraint(['VoucherID'], ['vouchers.VoucherID'], name=op.f('fk_inventories_VoucherID_vouchers')), + sa.PrimaryKeyConstraint('InventoryID', name=op.f('pk_inventories')), + sa.UniqueConstraint('VoucherID', 'BatchID', name=op.f('uq_inventories_VoucherID')) + ) + op.create_index(op.f('ix_inventories_VoucherID'), 'inventories', ['VoucherID'], unique=False) + op.create_table('recipe_items', + sa.Column('recipe_item_id', postgresql.UUID(), nullable=False), + sa.Column('recipe_id', postgresql.UUID(), nullable=False), + sa.Column('product_id', postgresql.UUID(), nullable=False), + sa.Column('quantity', sa.Integer(), nullable=False), + sa.Column('price', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['product_id'], ['products.ProductID'], name=op.f('fk_recipe_items_product_id_products')), + sa.ForeignKeyConstraint(['recipe_id'], ['recipes.recipe_id'], name=op.f('fk_recipe_items_recipe_id_recipes')), + sa.PrimaryKeyConstraint('recipe_item_id', name=op.f('pk_recipe_items')), + sa.UniqueConstraint('recipe_id', 'product_id', name=op.f('uq_recipe_items_recipe_id')) + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('recipe_items') + op.drop_index(op.f('ix_inventories_VoucherID'), table_name='inventories') + op.drop_table('inventories') + op.drop_table('service_charges') + op.drop_table('salary_deductions') + op.drop_table('recipes') + op.drop_table('fingerprints') + op.drop_table('batches') + op.drop_table('attendances') + op.drop_table('products') + op.drop_index(op.f('ix_journals_VoucherID'), table_name='journals') + op.drop_table('journals') + op.drop_table('employees') + op.drop_index(op.f('ix_vouchers_date'), table_name='vouchers') + op.drop_table('vouchers') + op.drop_table('auth_usergroups') + op.drop_table('auth_rolegroups') + op.drop_table('auth_login_history') + op.drop_table('accounts') + op.drop_table('settings') + op.drop_table('product_groups') + op.drop_table('images') + op.drop_table('cost_centres') + op.drop_table('auth_users') + op.drop_table('auth_roles') + op.drop_table('auth_groups') + op.drop_table('auth_clients') + # ### end Alembic commands ### diff --git a/alembic/versions/eed0b382c287_my_test.py b/alembic/versions/eed0b382c287_my_test.py new file mode 100644 index 00000000..5b7eb6c5 --- /dev/null +++ b/alembic/versions/eed0b382c287_my_test.py @@ -0,0 +1,538 @@ +"""my test + +Revision ID: eed0b382c287 +Revises: 0bf3d70ee7de +Create Date: 2020-05-10 19:52:58.163810 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = 'eed0b382c287' +down_revision = '0bf3d70ee7de' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('auth_permissions', + sa.Column('id', brewman.models.guidtype.GUID(), nullable=False), + sa.Column('name', sa.Unicode(length=255), nullable=True), + sa.PrimaryKeyConstraint('id', name=op.f('pk_auth_permissions')), + sa.UniqueConstraint('name', name=op.f('uq_auth_permissions_name')) + ) + op.create_table('role_permissions', + sa.Column('id', brewman.models.guidtype.GUID(), nullable=False), + sa.Column('permission_id', brewman.models.guidtype.GUID(), nullable=True), + sa.Column('role_id', brewman.models.guidtype.GUID(), nullable=True), + sa.ForeignKeyConstraint(['permission_id'], ['auth_permissions.id'], name=op.f('fk_role_permissions_permission_id_auth_permissions')), + sa.ForeignKeyConstraint(['role_id'], ['auth_roles.id'], name=op.f('fk_role_permissions_role_id_auth_roles')), + sa.PrimaryKeyConstraint('id', name=op.f('pk_role_permissions')) + ) + op.create_table('user_roles', + sa.Column('id', brewman.models.guidtype.GUID(), nullable=False), + sa.Column('user_id', brewman.models.guidtype.GUID(), nullable=True), + sa.Column('role_id', brewman.models.guidtype.GUID(), nullable=True), + sa.ForeignKeyConstraint(['role_id'], ['auth_roles.id'], name=op.f('fk_user_roles_role_id_auth_roles')), + sa.ForeignKeyConstraint(['user_id'], ['auth_users.id'], name=op.f('fk_user_roles_user_id_auth_users')), + sa.PrimaryKeyConstraint('id', name=op.f('pk_user_roles')) + ) + op.drop_table('msg_subscribers') + op.drop_table('auth_rolegroups') + op.drop_table('auth_groups') + op.drop_table('msg_posts') + op.drop_table('msg_threadtags') + op.drop_table('msg_threads') + op.drop_table('msg_tags') + op.drop_table('auth_usergroups') + op.create_unique_constraint(op.f('uq_accounts_name'), 'accounts', ['name']) + op.drop_constraint('accounts_name_key', 'accounts', type_='unique') + op.drop_constraint('accounts_cost_centre_id_fkey', 'accounts', type_='foreignkey') + op.create_foreign_key(op.f('fk_accounts_cost_centre_id_cost_centres'), 'accounts', 'cost_centres', ['cost_centre_id'], ['id']) + op.add_column('attendances', sa.Column('amount', sa.Numeric(), nullable=True)) + op.add_column('attendances', sa.Column('attendance_type', sa.Integer(), nullable=True)) + op.add_column('attendances', sa.Column('creation_date', sa.DateTime(timezone=True), nullable=True)) + op.add_column('attendances', sa.Column('date', sa.DateTime(), nullable=True)) + op.add_column('attendances', sa.Column('employee_id', brewman.models.guidtype.GUID(), nullable=True)) + op.add_column('attendances', sa.Column('id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('attendances', sa.Column('is_valid', sa.Boolean(), nullable=True)) + op.add_column('attendances', sa.Column('user_id', brewman.models.guidtype.GUID(), nullable=True)) + op.drop_constraint('entities_attendances_UserID_fkey', 'attendances', type_='foreignkey') + op.drop_constraint('entities_attendances_EmployeeID_fkey', 'attendances', type_='foreignkey') + op.create_foreign_key(op.f('fk_attendances_employee_id_employees'), 'attendances', 'employees', ['employee_id'], ['id']) + op.create_foreign_key(op.f('fk_attendances_user_id_auth_users'), 'attendances', 'auth_users', ['user_id'], ['id']) + op.drop_column('attendances', 'CreationDate') + op.drop_column('attendances', 'EmployeeID') + op.drop_column('attendances', 'Date') + op.drop_column('attendances', 'AttendanceID') + op.drop_column('attendances', 'Amount') + op.drop_column('attendances', 'AttendanceType') + op.drop_column('attendances', 'IsValid') + op.drop_column('attendances', 'UserID') + op.create_unique_constraint(op.f('uq_auth_clients_code'), 'auth_clients', ['code']) + op.create_unique_constraint(op.f('uq_auth_clients_name'), 'auth_clients', ['name']) + op.drop_constraint('auth_clients_Code_key', 'auth_clients', type_='unique') + op.drop_constraint('auth_clients_Name_key', 'auth_clients', type_='unique') + op.create_unique_constraint(op.f('uq_auth_login_history_user_id'), 'auth_login_history', ['user_id', 'client_id', 'date']) + op.drop_constraint('auth_login_history_user_id_client_id_date_key', 'auth_login_history', type_='unique') + op.drop_constraint('auth_login_history_user_id_fkey', 'auth_login_history', type_='foreignkey') + op.create_foreign_key(op.f('fk_auth_login_history_user_id_auth_users'), 'auth_login_history', 'auth_users', ['user_id'], ['id']) + op.add_column('auth_roles', sa.Column('id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('auth_roles', sa.Column('name', sa.Unicode(length=255), nullable=True)) + op.create_unique_constraint(op.f('uq_auth_roles_name'), 'auth_roles', ['name']) + op.drop_constraint('auth_roles_Name_key', 'auth_roles', type_='unique') + op.drop_column('auth_roles', 'RoleID') + op.drop_column('auth_roles', 'Name') + op.add_column('auth_users', sa.Column('disabled', sa.Boolean(), nullable=True)) + op.add_column('auth_users', sa.Column('id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('auth_users', sa.Column('password', sa.Unicode(length=60), nullable=True)) + op.add_column('auth_users', sa.Column('username', sa.Unicode(length=255), nullable=True)) + op.create_unique_constraint(op.f('uq_auth_users_username'), 'auth_users', ['username']) + op.drop_constraint('auth_users_Name_key', 'auth_users', type_='unique') + op.drop_column('auth_users', 'UserID') + op.drop_column('auth_users', 'Name') + op.drop_column('auth_users', 'Password') + op.drop_column('auth_users', 'LockedOut') + op.add_column('batches', sa.Column('discount', sa.Numeric(), nullable=True)) + op.add_column('batches', sa.Column('id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('batches', sa.Column('name', sa.DateTime(), nullable=True)) + op.add_column('batches', sa.Column('product_id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('batches', sa.Column('quantity_remaining', sa.Numeric(), nullable=True)) + op.add_column('batches', sa.Column('rate', sa.Numeric(), nullable=True)) + op.add_column('batches', sa.Column('tax', sa.Numeric(), nullable=True)) + op.drop_constraint('batches_ProductID_fkey', 'batches', type_='foreignkey') + op.create_foreign_key(op.f('fk_batches_product_id_products'), 'batches', 'products', ['product_id'], ['id']) + op.drop_column('batches', 'QuantityRemaining') + op.drop_column('batches', 'Rate') + op.drop_column('batches', 'Tax') + op.drop_column('batches', 'BatchID') + op.drop_column('batches', 'ProductID') + op.drop_column('batches', 'Name') + op.drop_column('batches', 'Discount') + op.add_column('cost_centres', sa.Column('id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('cost_centres', sa.Column('is_fixture', sa.Boolean(), nullable=False)) + op.add_column('cost_centres', sa.Column('name', sa.Unicode(length=255), nullable=True)) + op.create_unique_constraint(op.f('uq_cost_centres_name'), 'cost_centres', ['name']) + op.drop_constraint('entities_costcenters_Name_key', 'cost_centres', type_='unique') + op.drop_column('cost_centres', 'Name') + op.drop_column('cost_centres', 'IsFixture') + op.drop_column('cost_centres', 'CostCentreID') + op.add_column('fingerprints', sa.Column('date', sa.DateTime(), nullable=True)) + op.add_column('fingerprints', sa.Column('employee_id', brewman.models.guidtype.GUID(), nullable=True)) + op.add_column('fingerprints', sa.Column('id', brewman.models.guidtype.GUID(), nullable=False)) + op.drop_constraint('uq_employee_id_date', 'fingerprints', type_='unique') + op.drop_constraint('entities_fingerprints_EmployeeID_fkey', 'fingerprints', type_='foreignkey') + op.create_foreign_key(op.f('fk_fingerprints_employee_id_employees'), 'fingerprints', 'employees', ['employee_id'], ['id']) + op.drop_column('fingerprints', 'FingerprintID') + op.drop_column('fingerprints', 'EmployeeID') + op.drop_column('fingerprints', 'Date') + op.add_column('inventories', sa.Column('batch_id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('inventories', sa.Column('discount', sa.Numeric(), nullable=True)) + op.add_column('inventories', sa.Column('id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('inventories', sa.Column('product_id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('inventories', sa.Column('quantity', sa.Numeric(), nullable=True)) + op.add_column('inventories', sa.Column('rate', sa.Numeric(), nullable=True)) + op.add_column('inventories', sa.Column('tax', sa.Numeric(), nullable=True)) + op.add_column('inventories', sa.Column('voucher_id', brewman.models.guidtype.GUID(), nullable=False)) + op.create_index(op.f('ix_inventories_voucher_id'), 'inventories', ['voucher_id'], unique=False) + op.create_unique_constraint(op.f('uq_inventories_voucher_id'), 'inventories', ['voucher_id', 'batch_id']) + op.drop_index('ix_inventories_VoucherID', table_name='inventories') + op.drop_constraint('entities_inventories_BatchID_fkey', 'inventories', type_='foreignkey') + op.drop_constraint('inventories_VoucherID_fkey', 'inventories', type_='foreignkey') + op.drop_constraint('inventories_ProductID_fkey', 'inventories', type_='foreignkey') + op.create_foreign_key(op.f('fk_inventories_voucher_id_vouchers'), 'inventories', 'vouchers', ['voucher_id'], ['id']) + op.create_foreign_key(op.f('fk_inventories_batch_id_batches'), 'inventories', 'batches', ['batch_id'], ['id']) + op.create_foreign_key(op.f('fk_inventories_product_id_products'), 'inventories', 'products', ['product_id'], ['id']) + op.drop_column('inventories', 'InventoryID') + op.drop_column('inventories', 'VoucherID') + op.drop_column('inventories', 'Rate') + op.drop_column('inventories', 'Tax') + op.drop_column('inventories', 'BatchID') + op.drop_column('inventories', 'ProductID') + op.drop_column('inventories', 'Quantity') + op.drop_column('inventories', 'Discount') + op.add_column('journals', sa.Column('amount', sa.Numeric(), nullable=True)) + op.add_column('journals', sa.Column('cost_centre_id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('journals', sa.Column('debit', sa.Integer(), nullable=True)) + op.add_column('journals', sa.Column('id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('journals', sa.Column('voucher_id', brewman.models.guidtype.GUID(), nullable=False)) + op.create_index(op.f('ix_journals_voucher_id'), 'journals', ['voucher_id'], unique=False) + op.drop_index('ix_journals_VoucherID', table_name='journals') + op.drop_constraint('journals_VoucherID_fkey', 'journals', type_='foreignkey') + op.drop_constraint('entities_journals_CostCenterID_fkey', 'journals', type_='foreignkey') + op.create_foreign_key(op.f('fk_journals_cost_centre_id_cost_centres'), 'journals', 'cost_centres', ['cost_centre_id'], ['id']) + op.create_foreign_key(op.f('fk_journals_voucher_id_vouchers'), 'journals', 'vouchers', ['voucher_id'], ['id']) + op.drop_column('journals', 'Debit') + op.drop_column('journals', 'JournalID') + op.drop_column('journals', 'VoucherID') + op.drop_column('journals', 'Amount') + op.drop_column('journals', 'CostCentreID') + op.add_column('product_groups', sa.Column('id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('product_groups', sa.Column('is_fixture', sa.Boolean(), nullable=False)) + op.add_column('product_groups', sa.Column('name', sa.Unicode(length=255), nullable=True)) + op.create_unique_constraint(op.f('uq_product_groups_name'), 'product_groups', ['name']) + op.drop_constraint('entities_productgroups_Name_key', 'product_groups', type_='unique') + op.drop_column('product_groups', 'Name') + op.drop_column('product_groups', 'ProductGroupID') + op.drop_column('product_groups', 'IsFixture') + op.add_column('products', sa.Column('code', sa.Integer(), nullable=True)) + op.add_column('products', sa.Column('fraction', sa.Numeric(), nullable=False)) + op.add_column('products', sa.Column('fraction_units', sa.Unicode(length=255), nullable=False)) + op.add_column('products', sa.Column('id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('products', sa.Column('is_active', sa.Boolean(), nullable=False)) + op.add_column('products', sa.Column('is_fixture', sa.Boolean(), nullable=False)) + op.add_column('products', sa.Column('name', sa.Unicode(length=255), nullable=False)) + op.add_column('products', sa.Column('product_group_id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('products', sa.Column('product_yield', sa.Numeric(), nullable=False)) + op.add_column('products', sa.Column('units', sa.Unicode(length=255), nullable=False)) + op.create_unique_constraint(op.f('uq_products_code'), 'products', ['code']) + op.create_unique_constraint(op.f('uq_products_name'), 'products', ['name', 'units']) + op.drop_constraint('products_Code_key', 'products', type_='unique') + op.drop_constraint('products_Name_Units_key', 'products', type_='unique') + op.drop_constraint('products_ProductGroupID_fkey', 'products', type_='foreignkey') + op.create_foreign_key(op.f('fk_products_product_group_id_product_groups'), 'products', 'product_groups', ['product_group_id'], ['id']) + op.drop_column('products', 'Fraction') + op.drop_column('products', 'Units') + op.drop_column('products', 'ProductGroupID') + op.drop_column('products', 'IsFixture') + op.drop_column('products', 'FractionUnits') + op.drop_column('products', 'Code') + op.drop_column('products', 'ProductID') + op.drop_column('products', 'IsActive') + op.drop_column('products', 'Name') + op.drop_column('products', 'ProductYield') + op.create_unique_constraint(op.f('uq_recipe_items_recipe_id'), 'recipe_items', ['recipe_id', 'product_id']) + op.drop_constraint('recipe_items_recipe_id_product_id_key', 'recipe_items', type_='unique') + op.drop_constraint('recipe_items_recipe_id_fkey', 'recipe_items', type_='foreignkey') + op.drop_constraint('recipe_items_product_id_fkey', 'recipe_items', type_='foreignkey') + op.create_foreign_key(op.f('fk_recipe_items_product_id_products'), 'recipe_items', 'products', ['product_id'], ['id']) + op.create_foreign_key(op.f('fk_recipe_items_recipe_id_recipes'), 'recipe_items', 'recipes', ['recipe_id'], ['id']) + op.add_column('recipes', sa.Column('id', brewman.models.guidtype.GUID(), nullable=False)) + op.drop_constraint('recipes_product_id_fkey', 'recipes', type_='foreignkey') + op.create_foreign_key(op.f('fk_recipes_product_id_products'), 'recipes', 'products', ['product_id'], ['id']) + op.drop_column('recipes', 'recipe_id') + op.add_column('salary_deductions', sa.Column('days_worked', sa.Integer(), nullable=True)) + op.add_column('salary_deductions', sa.Column('esi_employee', sa.Integer(), nullable=True)) + op.add_column('salary_deductions', sa.Column('esi_employer', sa.Integer(), nullable=True)) + op.add_column('salary_deductions', sa.Column('gross_salary', sa.Integer(), nullable=True)) + op.add_column('salary_deductions', sa.Column('id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('salary_deductions', sa.Column('journal_id', brewman.models.guidtype.GUID(), nullable=False)) + op.add_column('salary_deductions', sa.Column('pf_employee', sa.Integer(), nullable=True)) + op.add_column('salary_deductions', sa.Column('pf_employer', sa.Integer(), nullable=True)) + op.add_column('salary_deductions', sa.Column('voucher_id', brewman.models.guidtype.GUID(), nullable=False)) + op.drop_constraint('entities_salarydeductions_JournalID_fkey', 'salary_deductions', type_='foreignkey') + op.drop_constraint('salary_deductions_VoucherID_fkey', 'salary_deductions', type_='foreignkey') + op.create_foreign_key(op.f('fk_salary_deductions_voucher_id_vouchers'), 'salary_deductions', 'vouchers', ['voucher_id'], ['id']) + op.create_foreign_key(op.f('fk_salary_deductions_journal_id_journals'), 'salary_deductions', 'journals', ['journal_id'], ['id']) + op.drop_column('salary_deductions', 'JournalID') + op.drop_column('salary_deductions', 'VoucherID') + op.drop_column('salary_deductions', 'EsiEmployee') + op.drop_column('salary_deductions', 'PfEmployer') + op.drop_column('salary_deductions', 'DaysWorked') + op.drop_column('salary_deductions', 'GrossSalary') + op.drop_column('salary_deductions', 'PfEmployee') + op.drop_column('salary_deductions', 'SalaryDeductionID') + op.drop_column('salary_deductions', 'EsiEmployer') + op.drop_constraint('service_charges_journal_id_fkey', 'service_charges', type_='foreignkey') + op.drop_constraint('service_charges_voucher_id_fkey', 'service_charges', type_='foreignkey') + op.create_foreign_key(op.f('fk_service_charges_journal_id_journals'), 'service_charges', 'journals', ['journal_id'], ['id']) + op.create_foreign_key(op.f('fk_service_charges_voucher_id_vouchers'), 'service_charges', 'vouchers', ['voucher_id'], ['id']) + op.create_unique_constraint(op.f('uq_settings_Name'), 'settings', ['Name']) + op.drop_constraint('settings_Name_key', 'settings', type_='unique') + # op.add_column('vouchers', sa.Column('id', postgresql.UUID(), nullable=False)) + op.create_index(op.f('ix_vouchers_date'), 'vouchers', ['date'], unique=False) + + op.drop_constraint('vouchers_poster_id_fkey', 'vouchers', type_='foreignkey') + op.drop_constraint('vouchers_user_id_fkey', 'vouchers', type_='foreignkey') + op.create_foreign_key(op.f('fk_vouchers_user_id_auth_users'), 'vouchers', 'auth_users', ['user_id'], ['id']) + op.create_foreign_key(op.f('fk_vouchers_poster_id_auth_users'), 'vouchers', 'auth_users', ['poster_id'], ['id']) + with op.batch_alter_table("vouchers") as batch_op: + batch_op.alter_column('vouchers', 'VoucherID', new_column_name='id') + # op.drop_column('vouchers', 'VoucherID') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('vouchers', sa.Column('VoucherID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.drop_constraint(op.f('fk_vouchers_poster_id_auth_users'), 'vouchers', type_='foreignkey') + op.drop_constraint(op.f('fk_vouchers_user_id_auth_users'), 'vouchers', type_='foreignkey') + op.create_foreign_key('vouchers_user_id_fkey', 'vouchers', 'auth_users', ['user_id'], ['UserID']) + op.create_foreign_key('vouchers_poster_id_fkey', 'vouchers', 'auth_users', ['poster_id'], ['UserID']) + op.drop_index(op.f('ix_vouchers_date'), table_name='vouchers') + op.drop_column('vouchers', 'id') + op.create_unique_constraint('settings_Name_key', 'settings', ['Name']) + op.drop_constraint(op.f('uq_settings_Name'), 'settings', type_='unique') + op.drop_constraint(op.f('fk_service_charges_voucher_id_vouchers'), 'service_charges', type_='foreignkey') + op.drop_constraint(op.f('fk_service_charges_journal_id_journals'), 'service_charges', type_='foreignkey') + op.create_foreign_key('service_charges_voucher_id_fkey', 'service_charges', 'vouchers', ['voucher_id'], ['VoucherID']) + op.create_foreign_key('service_charges_journal_id_fkey', 'service_charges', 'journals', ['journal_id'], ['JournalID']) + op.add_column('salary_deductions', sa.Column('EsiEmployer', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('salary_deductions', sa.Column('SalaryDeductionID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('salary_deductions', sa.Column('PfEmployee', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('salary_deductions', sa.Column('GrossSalary', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('salary_deductions', sa.Column('DaysWorked', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('salary_deductions', sa.Column('PfEmployer', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('salary_deductions', sa.Column('EsiEmployee', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('salary_deductions', sa.Column('VoucherID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('salary_deductions', sa.Column('JournalID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.drop_constraint(op.f('fk_salary_deductions_journal_id_journals'), 'salary_deductions', type_='foreignkey') + op.drop_constraint(op.f('fk_salary_deductions_voucher_id_vouchers'), 'salary_deductions', type_='foreignkey') + op.create_foreign_key('salary_deductions_VoucherID_fkey', 'salary_deductions', 'vouchers', ['VoucherID'], ['VoucherID']) + op.create_foreign_key('entities_salarydeductions_JournalID_fkey', 'salary_deductions', 'journals', ['JournalID'], ['JournalID']) + op.drop_column('salary_deductions', 'voucher_id') + op.drop_column('salary_deductions', 'pf_employer') + op.drop_column('salary_deductions', 'pf_employee') + op.drop_column('salary_deductions', 'journal_id') + op.drop_column('salary_deductions', 'id') + op.drop_column('salary_deductions', 'gross_salary') + op.drop_column('salary_deductions', 'esi_employer') + op.drop_column('salary_deductions', 'esi_employee') + op.drop_column('salary_deductions', 'days_worked') + op.add_column('recipes', sa.Column('recipe_id', postgresql.UUID(), autoincrement=False, nullable=False)) + op.drop_constraint(op.f('fk_recipes_product_id_products'), 'recipes', type_='foreignkey') + op.create_foreign_key('recipes_product_id_fkey', 'recipes', 'products', ['product_id'], ['ProductID']) + op.drop_column('recipes', 'id') + op.drop_constraint(op.f('fk_recipe_items_recipe_id_recipes'), 'recipe_items', type_='foreignkey') + op.drop_constraint(op.f('fk_recipe_items_product_id_products'), 'recipe_items', type_='foreignkey') + op.create_foreign_key('recipe_items_product_id_fkey', 'recipe_items', 'products', ['product_id'], ['ProductID']) + op.create_foreign_key('recipe_items_recipe_id_fkey', 'recipe_items', 'recipes', ['recipe_id'], ['recipe_id']) + op.create_unique_constraint('recipe_items_recipe_id_product_id_key', 'recipe_items', ['recipe_id', 'product_id']) + op.drop_constraint(op.f('uq_recipe_items_recipe_id'), 'recipe_items', type_='unique') + op.add_column('products', sa.Column('ProductYield', sa.NUMERIC(), autoincrement=False, nullable=False)) + op.add_column('products', sa.Column('Name', sa.VARCHAR(length=255), autoincrement=False, nullable=False)) + op.add_column('products', sa.Column('IsActive', sa.BOOLEAN(), autoincrement=False, nullable=False)) + op.add_column('products', sa.Column('ProductID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('products', sa.Column('Code', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('products', sa.Column('FractionUnits', sa.VARCHAR(length=255), autoincrement=False, nullable=False)) + op.add_column('products', sa.Column('IsFixture', sa.BOOLEAN(), autoincrement=False, nullable=False)) + op.add_column('products', sa.Column('ProductGroupID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('products', sa.Column('Units', sa.VARCHAR(length=255), autoincrement=False, nullable=False)) + op.add_column('products', sa.Column('Fraction', sa.NUMERIC(), autoincrement=False, nullable=False)) + op.drop_constraint(op.f('fk_products_product_group_id_product_groups'), 'products', type_='foreignkey') + op.create_foreign_key('products_ProductGroupID_fkey', 'products', 'product_groups', ['ProductGroupID'], ['ProductGroupID']) + op.create_unique_constraint('products_Name_Units_key', 'products', ['Name', 'Units']) + op.create_unique_constraint('products_Code_key', 'products', ['Code']) + op.drop_constraint(op.f('uq_products_name'), 'products', type_='unique') + op.drop_constraint(op.f('uq_products_code'), 'products', type_='unique') + op.drop_column('products', 'units') + op.drop_column('products', 'product_yield') + op.drop_column('products', 'product_group_id') + op.drop_column('products', 'name') + op.drop_column('products', 'is_fixture') + op.drop_column('products', 'is_active') + op.drop_column('products', 'id') + op.drop_column('products', 'fraction_units') + op.drop_column('products', 'fraction') + op.drop_column('products', 'code') + op.add_column('product_groups', sa.Column('IsFixture', sa.BOOLEAN(), autoincrement=False, nullable=False)) + op.add_column('product_groups', sa.Column('ProductGroupID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('product_groups', sa.Column('Name', sa.VARCHAR(length=255), autoincrement=False, nullable=True)) + op.create_unique_constraint('entities_productgroups_Name_key', 'product_groups', ['Name']) + op.drop_constraint(op.f('uq_product_groups_name'), 'product_groups', type_='unique') + op.drop_column('product_groups', 'name') + op.drop_column('product_groups', 'is_fixture') + op.drop_column('product_groups', 'id') + op.add_column('journals', sa.Column('CostCentreID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('journals', sa.Column('Amount', sa.NUMERIC(), autoincrement=False, nullable=True)) + op.add_column('journals', sa.Column('VoucherID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('journals', sa.Column('JournalID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('journals', sa.Column('Debit', sa.INTEGER(), autoincrement=False, nullable=True)) + op.drop_constraint(op.f('fk_journals_voucher_id_vouchers'), 'journals', type_='foreignkey') + op.drop_constraint(op.f('fk_journals_cost_centre_id_cost_centres'), 'journals', type_='foreignkey') + op.create_foreign_key('entities_journals_CostCenterID_fkey', 'journals', 'cost_centres', ['CostCentreID'], ['CostCentreID']) + op.create_foreign_key('journals_VoucherID_fkey', 'journals', 'vouchers', ['VoucherID'], ['VoucherID']) + op.create_index('ix_journals_VoucherID', 'journals', ['VoucherID'], unique=False) + op.drop_index(op.f('ix_journals_voucher_id'), table_name='journals') + op.drop_column('journals', 'voucher_id') + op.drop_column('journals', 'id') + op.drop_column('journals', 'debit') + op.drop_column('journals', 'cost_centre_id') + op.drop_column('journals', 'amount') + op.add_column('inventories', sa.Column('Discount', sa.NUMERIC(), autoincrement=False, nullable=True)) + op.add_column('inventories', sa.Column('Quantity', sa.NUMERIC(), autoincrement=False, nullable=True)) + op.add_column('inventories', sa.Column('ProductID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('inventories', sa.Column('BatchID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('inventories', sa.Column('Tax', sa.NUMERIC(), autoincrement=False, nullable=True)) + op.add_column('inventories', sa.Column('Rate', sa.NUMERIC(), autoincrement=False, nullable=True)) + op.add_column('inventories', sa.Column('VoucherID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('inventories', sa.Column('InventoryID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.drop_constraint(op.f('fk_inventories_product_id_products'), 'inventories', type_='foreignkey') + op.drop_constraint(op.f('fk_inventories_batch_id_batches'), 'inventories', type_='foreignkey') + op.drop_constraint(op.f('fk_inventories_voucher_id_vouchers'), 'inventories', type_='foreignkey') + op.create_foreign_key('inventories_ProductID_fkey', 'inventories', 'products', ['ProductID'], ['ProductID']) + op.create_foreign_key('inventories_VoucherID_fkey', 'inventories', 'vouchers', ['VoucherID'], ['VoucherID']) + op.create_foreign_key('entities_inventories_BatchID_fkey', 'inventories', 'batches', ['BatchID'], ['BatchID']) + op.create_index('ix_inventories_VoucherID', 'inventories', ['VoucherID'], unique=False) + op.drop_constraint(op.f('uq_inventories_voucher_id'), 'inventories', type_='unique') + op.drop_index(op.f('ix_inventories_voucher_id'), table_name='inventories') + op.drop_column('inventories', 'voucher_id') + op.drop_column('inventories', 'tax') + op.drop_column('inventories', 'rate') + op.drop_column('inventories', 'quantity') + op.drop_column('inventories', 'product_id') + op.drop_column('inventories', 'id') + op.drop_column('inventories', 'discount') + op.drop_column('inventories', 'batch_id') + op.add_column('fingerprints', sa.Column('Date', postgresql.TIMESTAMP(), autoincrement=False, nullable=True)) + op.add_column('fingerprints', sa.Column('EmployeeID', postgresql.UUID(), autoincrement=False, nullable=True)) + op.add_column('fingerprints', sa.Column('FingerprintID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.drop_constraint(op.f('fk_fingerprints_employee_id_employees'), 'fingerprints', type_='foreignkey') + op.create_foreign_key('entities_fingerprints_EmployeeID_fkey', 'fingerprints', 'employees', ['EmployeeID'], ['id']) + op.create_unique_constraint('uq_employee_id_date', 'fingerprints', ['EmployeeID', 'Date']) + op.drop_column('fingerprints', 'id') + op.drop_column('fingerprints', 'employee_id') + op.drop_column('fingerprints', 'date') + op.add_column('cost_centres', sa.Column('CostCentreID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('cost_centres', sa.Column('IsFixture', sa.BOOLEAN(), autoincrement=False, nullable=False)) + op.add_column('cost_centres', sa.Column('Name', sa.VARCHAR(length=255), autoincrement=False, nullable=True)) + op.create_unique_constraint('entities_costcenters_Name_key', 'cost_centres', ['Name']) + op.drop_constraint(op.f('uq_cost_centres_name'), 'cost_centres', type_='unique') + op.drop_column('cost_centres', 'name') + op.drop_column('cost_centres', 'is_fixture') + op.drop_column('cost_centres', 'id') + op.add_column('batches', sa.Column('Discount', sa.NUMERIC(), autoincrement=False, nullable=True)) + op.add_column('batches', sa.Column('Name', postgresql.TIMESTAMP(), autoincrement=False, nullable=True)) + op.add_column('batches', sa.Column('ProductID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('batches', sa.Column('BatchID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('batches', sa.Column('Tax', sa.NUMERIC(), autoincrement=False, nullable=True)) + op.add_column('batches', sa.Column('Rate', sa.NUMERIC(), autoincrement=False, nullable=True)) + op.add_column('batches', sa.Column('QuantityRemaining', sa.NUMERIC(), autoincrement=False, nullable=True)) + op.drop_constraint(op.f('fk_batches_product_id_products'), 'batches', type_='foreignkey') + op.create_foreign_key('batches_ProductID_fkey', 'batches', 'products', ['ProductID'], ['ProductID']) + op.drop_column('batches', 'tax') + op.drop_column('batches', 'rate') + op.drop_column('batches', 'quantity_remaining') + op.drop_column('batches', 'product_id') + op.drop_column('batches', 'name') + op.drop_column('batches', 'id') + op.drop_column('batches', 'discount') + op.add_column('auth_users', sa.Column('LockedOut', sa.BOOLEAN(), autoincrement=False, nullable=True)) + op.add_column('auth_users', sa.Column('Password', sa.VARCHAR(length=60), autoincrement=False, nullable=True)) + op.add_column('auth_users', sa.Column('Name', sa.VARCHAR(length=255), autoincrement=False, nullable=True)) + op.add_column('auth_users', sa.Column('UserID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.create_unique_constraint('auth_users_Name_key', 'auth_users', ['Name']) + op.drop_constraint(op.f('uq_auth_users_username'), 'auth_users', type_='unique') + op.drop_column('auth_users', 'username') + op.drop_column('auth_users', 'password') + op.drop_column('auth_users', 'id') + op.drop_column('auth_users', 'disabled') + op.add_column('auth_roles', sa.Column('Name', sa.VARCHAR(length=255), autoincrement=False, nullable=True)) + op.add_column('auth_roles', sa.Column('RoleID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.create_unique_constraint('auth_roles_Name_key', 'auth_roles', ['Name']) + op.drop_constraint(op.f('uq_auth_roles_name'), 'auth_roles', type_='unique') + op.drop_column('auth_roles', 'name') + op.drop_column('auth_roles', 'id') + op.drop_constraint(op.f('fk_auth_login_history_user_id_auth_users'), 'auth_login_history', type_='foreignkey') + op.create_foreign_key('auth_login_history_user_id_fkey', 'auth_login_history', 'auth_users', ['user_id'], ['UserID']) + op.create_unique_constraint('auth_login_history_user_id_client_id_date_key', 'auth_login_history', ['user_id', 'client_id', 'date']) + op.drop_constraint(op.f('uq_auth_login_history_user_id'), 'auth_login_history', type_='unique') + op.create_unique_constraint('auth_clients_Name_key', 'auth_clients', ['name']) + op.create_unique_constraint('auth_clients_Code_key', 'auth_clients', ['code']) + op.drop_constraint(op.f('uq_auth_clients_name'), 'auth_clients', type_='unique') + op.drop_constraint(op.f('uq_auth_clients_code'), 'auth_clients', type_='unique') + op.add_column('attendances', sa.Column('UserID', postgresql.UUID(), autoincrement=False, nullable=True)) + op.add_column('attendances', sa.Column('IsValid', sa.BOOLEAN(), autoincrement=False, nullable=True)) + op.add_column('attendances', sa.Column('AttendanceType', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('attendances', sa.Column('Amount', sa.NUMERIC(), autoincrement=False, nullable=True)) + op.add_column('attendances', sa.Column('AttendanceID', postgresql.UUID(), autoincrement=False, nullable=False)) + op.add_column('attendances', sa.Column('Date', postgresql.TIMESTAMP(), autoincrement=False, nullable=True)) + op.add_column('attendances', sa.Column('EmployeeID', postgresql.UUID(), autoincrement=False, nullable=True)) + op.add_column('attendances', sa.Column('CreationDate', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=True)) + op.drop_constraint(op.f('fk_attendances_user_id_auth_users'), 'attendances', type_='foreignkey') + op.drop_constraint(op.f('fk_attendances_employee_id_employees'), 'attendances', type_='foreignkey') + op.create_foreign_key('entities_attendances_EmployeeID_fkey', 'attendances', 'employees', ['EmployeeID'], ['id']) + op.create_foreign_key('entities_attendances_UserID_fkey', 'attendances', 'auth_users', ['UserID'], ['UserID']) + op.drop_column('attendances', 'user_id') + op.drop_column('attendances', 'is_valid') + op.drop_column('attendances', 'id') + op.drop_column('attendances', 'employee_id') + op.drop_column('attendances', 'date') + op.drop_column('attendances', 'creation_date') + op.drop_column('attendances', 'attendance_type') + op.drop_column('attendances', 'amount') + op.drop_constraint(op.f('fk_accounts_cost_centre_id_cost_centres'), 'accounts', type_='foreignkey') + op.create_foreign_key('accounts_cost_centre_id_fkey', 'accounts', 'cost_centres', ['cost_centre_id'], ['CostCentreID']) + op.create_unique_constraint('accounts_name_key', 'accounts', ['name']) + op.drop_constraint(op.f('uq_accounts_name'), 'accounts', type_='unique') + op.create_table('auth_usergroups', + sa.Column('UserGroupID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('UserID', postgresql.UUID(), autoincrement=False, nullable=True), + sa.Column('GroupID', postgresql.UUID(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['GroupID'], ['auth_groups.GroupID'], name='auth_usergroups_GroupID_fkey'), + sa.ForeignKeyConstraint(['UserID'], ['auth_users.UserID'], name='auth_usergroups_UserID_fkey'), + sa.PrimaryKeyConstraint('UserGroupID', name='auth_usergroups_pkey') + ) + op.create_table('msg_tags', + sa.Column('TagID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Name', sa.VARCHAR(length=100), autoincrement=False, nullable=False), + sa.Column('CssClass', sa.VARCHAR(length=100), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('TagID', name='msg_tags_pkey'), + sa.UniqueConstraint('Name', name='msg_tags_Name_key'), + postgresql_ignore_search_path=False + ) + op.create_table('msg_threads', + sa.Column('ThreadID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Title', sa.VARCHAR(length=1000), autoincrement=False, nullable=False), + sa.Column('CreationDate', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=False), + sa.Column('UserID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Priority', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('Public', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.Column('Closed', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['UserID'], ['auth_users.UserID'], name='msg_threads_UserID_fkey'), + sa.PrimaryKeyConstraint('ThreadID', name='msg_threads_pkey'), + sa.UniqueConstraint('Title', name='msg_threads_Title_key'), + postgresql_ignore_search_path=False + ) + op.create_table('msg_threadtags', + sa.Column('ThreadTagID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('ThreadID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('TagID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['TagID'], ['msg_tags.TagID'], name='msg_threadtags_TagID_fkey'), + sa.ForeignKeyConstraint(['ThreadID'], ['msg_threads.ThreadID'], name='msg_threadtags_ThreadID_fkey'), + sa.PrimaryKeyConstraint('ThreadTagID', name='msg_threadtags_pkey'), + sa.UniqueConstraint('ThreadID', 'TagID', name='msg_threadtags_ThreadID_TagID_key') + ) + op.create_table('msg_posts', + sa.Column('PostID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Content', sa.VARCHAR(length=1000), autoincrement=False, nullable=False), + sa.Column('CreationDate', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=False), + sa.Column('UserID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Date', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), + sa.Column('ThreadID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['ThreadID'], ['msg_threads.ThreadID'], name='msg_posts_ThreadID_fkey'), + sa.ForeignKeyConstraint(['UserID'], ['auth_users.UserID'], name='msg_posts_UserID_fkey'), + sa.PrimaryKeyConstraint('PostID', name='msg_posts_pkey') + ) + op.create_table('auth_groups', + sa.Column('GroupID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Name', sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('GroupID', name='auth_groups_pkey'), + sa.UniqueConstraint('Name', name='auth_groups_Name_key'), + postgresql_ignore_search_path=False + ) + op.create_table('auth_rolegroups', + sa.Column('RoleGroupID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('RoleID', postgresql.UUID(), autoincrement=False, nullable=True), + sa.Column('GroupID', postgresql.UUID(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['GroupID'], ['auth_groups.GroupID'], name='auth_rolegroups_GroupID_fkey'), + sa.ForeignKeyConstraint(['RoleID'], ['auth_roles.RoleID'], name='auth_rolegroups_RoleID_fkey'), + sa.PrimaryKeyConstraint('RoleGroupID', name='auth_rolegroups_pkey') + ) + op.create_table('msg_subscribers', + sa.Column('SubscriberID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('ThreadID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('UserID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Read', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['ThreadID'], ['msg_threads.ThreadID'], name='msg_subscribers_ThreadID_fkey'), + sa.ForeignKeyConstraint(['UserID'], ['auth_users.UserID'], name='msg_subscribers_UserID_fkey'), + sa.PrimaryKeyConstraint('SubscriberID', name='msg_subscribers_pkey'), + sa.UniqueConstraint('ThreadID', 'UserID', name='msg_subscribers_ThreadID_UserID_key') + ) + op.drop_table('user_roles') + op.drop_table('role_permissions') + op.drop_table('auth_permissions') + # ### end Alembic commands ### diff --git a/bc2f5ea0c0d7_my_test.py b/bc2f5ea0c0d7_my_test.py new file mode 100644 index 00000000..7a018ba0 --- /dev/null +++ b/bc2f5ea0c0d7_my_test.py @@ -0,0 +1,378 @@ +"""my test + +Revision ID: bc2f5ea0c0d7 +Revises: +Create Date: 2020-05-10 18:18:15.377295 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = 'bc2f5ea0c0d7' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('salary_deductions') + op.drop_table('auth_clients') + op.drop_table('auth_usergroups') + op.drop_index('ix_inventories_VoucherID', table_name='inventories') + op.drop_table('inventories') + op.drop_table('employees') + op.drop_table('msg_threadtags') + op.drop_table('fingerprints') + op.drop_table('products') + op.drop_table('cost_centres') + op.drop_table('attendances') + op.drop_table('product_groups') + op.drop_table('accounts') + op.drop_table('recipe_items') + op.drop_table('auth_users') + op.drop_table('msg_subscribers') + op.drop_table('auth_roles') + op.drop_table('msg_tags') + op.drop_table('images') + op.drop_table('vouchers') + op.drop_table('msg_threads') + op.drop_table('auth_rolegroups') + op.drop_table('batches') + op.drop_index('ix_journals_VoucherID', table_name='journals') + op.drop_table('journals') + op.drop_table('service_charges') + op.drop_table('recipes') + op.drop_table('settings') + op.drop_table('auth_login_history') + op.drop_table('auth_groups') + op.drop_table('msg_posts') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('msg_posts', + sa.Column('PostID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Content', sa.VARCHAR(length=1000), autoincrement=False, nullable=False), + sa.Column('CreationDate', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=False), + sa.Column('UserID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Date', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), + sa.Column('ThreadID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['ThreadID'], ['msg_threads.ThreadID'], name='msg_posts_ThreadID_fkey'), + sa.ForeignKeyConstraint(['UserID'], ['auth_users.UserID'], name='msg_posts_UserID_fkey'), + sa.PrimaryKeyConstraint('PostID', name='msg_posts_pkey') + ) + op.create_table('auth_groups', + sa.Column('GroupID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Name', sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('GroupID', name='auth_groups_pkey'), + sa.UniqueConstraint('Name', name='auth_groups_Name_key'), + postgresql_ignore_search_path=False + ) + op.create_table('auth_login_history', + sa.Column('login_history_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('user_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('client_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('date', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['client_id'], ['auth_clients.client_id'], name='auth_login_history_client_id_fkey'), + sa.ForeignKeyConstraint(['user_id'], ['auth_users.UserID'], name='auth_login_history_user_id_fkey'), + sa.PrimaryKeyConstraint('login_history_id', name='auth_login_history_pkey'), + sa.UniqueConstraint('user_id', 'client_id', 'date', name='auth_login_history_user_id_client_id_date_key') + ) + op.create_table('settings', + sa.Column('SettingID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Name', sa.VARCHAR(length=255), autoincrement=False, nullable=False), + sa.Column('Data', postgresql.BYTEA(), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('SettingID', name='settings_pkey'), + sa.UniqueConstraint('Name', name='settings_Name_key') + ) + op.create_table('recipes', + sa.Column('recipe_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('product_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('quantity', sa.NUMERIC(), autoincrement=False, nullable=False), + sa.Column('cost_price', sa.NUMERIC(), autoincrement=False, nullable=False), + sa.Column('sale_price', sa.NUMERIC(), autoincrement=False, nullable=False), + sa.Column('notes', sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.Column('valid_from', sa.DATE(), autoincrement=False, nullable=False), + sa.Column('valid_to', sa.DATE(), autoincrement=False, nullable=False), + sa.Column('effective_from', sa.DATE(), autoincrement=False, nullable=False), + sa.Column('effective_to', sa.DATE(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['product_id'], ['products.ProductID'], name='recipes_product_id_fkey'), + sa.PrimaryKeyConstraint('recipe_id', name='recipes_pkey'), + postgresql_ignore_search_path=False + ) + op.create_table('service_charges', + sa.Column('id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('voucher_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('journal_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('days_worked', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('points', sa.NUMERIC(precision=5, scale=2), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['journal_id'], ['journals.JournalID'], name='service_charges_journal_id_fkey'), + sa.ForeignKeyConstraint(['voucher_id'], ['vouchers.VoucherID'], name='service_charges_voucher_id_fkey'), + sa.PrimaryKeyConstraint('id', name='service_charges_pkey') + ) + op.create_table('journals', + sa.Column('JournalID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Debit', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('Amount', sa.NUMERIC(), autoincrement=False, nullable=True), + sa.Column('VoucherID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('account_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('CostCentreID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['CostCentreID'], ['cost_centres.CostCentreID'], name='entities_journals_CostCenterID_fkey'), + sa.ForeignKeyConstraint(['VoucherID'], ['vouchers.VoucherID'], name='journals_VoucherID_fkey'), + sa.ForeignKeyConstraint(['account_id'], ['accounts.id'], name='journals_account_id_fkey'), + sa.PrimaryKeyConstraint('JournalID', name='entities_journals_pkey'), + postgresql_ignore_search_path=False + ) + op.create_index('ix_journals_VoucherID', 'journals', ['VoucherID'], unique=False) + op.create_table('batches', + sa.Column('BatchID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Name', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), + sa.Column('ProductID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('QuantityRemaining', sa.NUMERIC(), autoincrement=False, nullable=True), + sa.Column('Rate', sa.NUMERIC(), autoincrement=False, nullable=True), + sa.Column('Tax', sa.NUMERIC(), autoincrement=False, nullable=True), + sa.Column('Discount', sa.NUMERIC(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['ProductID'], ['products.ProductID'], name='batches_ProductID_fkey'), + sa.PrimaryKeyConstraint('BatchID', name='entities_batches_pkey'), + postgresql_ignore_search_path=False + ) + op.create_table('auth_rolegroups', + sa.Column('RoleGroupID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('RoleID', postgresql.UUID(), autoincrement=False, nullable=True), + sa.Column('GroupID', postgresql.UUID(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['GroupID'], ['auth_groups.GroupID'], name='auth_rolegroups_GroupID_fkey'), + sa.ForeignKeyConstraint(['RoleID'], ['auth_roles.RoleID'], name='auth_rolegroups_RoleID_fkey'), + sa.PrimaryKeyConstraint('RoleGroupID', name='auth_rolegroups_pkey') + ) + op.create_table('msg_threads', + sa.Column('ThreadID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Title', sa.VARCHAR(length=1000), autoincrement=False, nullable=False), + sa.Column('CreationDate', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=False), + sa.Column('UserID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Priority', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('Public', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.Column('Closed', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['UserID'], ['auth_users.UserID'], name='msg_threads_UserID_fkey'), + sa.PrimaryKeyConstraint('ThreadID', name='msg_threads_pkey'), + sa.UniqueConstraint('Title', name='msg_threads_Title_key'), + postgresql_ignore_search_path=False + ) + op.create_table('vouchers', + sa.Column('VoucherID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('date', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), + sa.Column('narration', sa.VARCHAR(length=1000), autoincrement=False, nullable=False), + sa.Column('creation_date', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=False), + sa.Column('last_edit_date', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=False), + sa.Column('voucher_type', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('is_posted', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.Column('poster_id', postgresql.UUID(), autoincrement=False, nullable=True), + sa.Column('user_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('is_reconciled', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.Column('reconcile_date', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), + sa.Column('is_starred', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['poster_id'], ['auth_users.UserID'], name='vouchers_poster_id_fkey'), + sa.ForeignKeyConstraint(['user_id'], ['auth_users.UserID'], name='vouchers_user_id_fkey'), + sa.PrimaryKeyConstraint('VoucherID', name='vouchers_pkey'), + postgresql_ignore_search_path=False + ) + op.create_table('images', + sa.Column('id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('resource_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('resource_type', sa.VARCHAR(length=255), autoincrement=False, nullable=False), + sa.Column('image', postgresql.BYTEA(), autoincrement=False, nullable=False), + sa.Column('thumbnail', postgresql.BYTEA(), autoincrement=False, nullable=False), + sa.Column('creation_date', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=False), + sa.PrimaryKeyConstraint('id', name='images_pkey') + ) + op.create_table('msg_tags', + sa.Column('TagID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Name', sa.VARCHAR(length=100), autoincrement=False, nullable=False), + sa.Column('CssClass', sa.VARCHAR(length=100), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('TagID', name='msg_tags_pkey'), + sa.UniqueConstraint('Name', name='msg_tags_Name_key'), + postgresql_ignore_search_path=False + ) + op.create_table('auth_roles', + sa.Column('RoleID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Name', sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('RoleID', name='auth_roles_pkey'), + sa.UniqueConstraint('Name', name='auth_roles_Name_key') + ) + op.create_table('msg_subscribers', + sa.Column('SubscriberID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('ThreadID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('UserID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Read', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['ThreadID'], ['msg_threads.ThreadID'], name='msg_subscribers_ThreadID_fkey'), + sa.ForeignKeyConstraint(['UserID'], ['auth_users.UserID'], name='msg_subscribers_UserID_fkey'), + sa.PrimaryKeyConstraint('SubscriberID', name='msg_subscribers_pkey'), + sa.UniqueConstraint('ThreadID', 'UserID', name='msg_subscribers_ThreadID_UserID_key') + ) + op.create_table('auth_users', + sa.Column('UserID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Name', sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.Column('Password', sa.VARCHAR(length=60), autoincrement=False, nullable=True), + sa.Column('LockedOut', sa.BOOLEAN(), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('UserID', name='auth_users_pkey'), + sa.UniqueConstraint('Name', name='auth_users_Name_key'), + postgresql_ignore_search_path=False + ) + op.create_table('recipe_items', + sa.Column('recipe_item_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('recipe_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('product_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('quantity', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('price', sa.INTEGER(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['product_id'], ['products.ProductID'], name='recipe_items_product_id_fkey'), + sa.ForeignKeyConstraint(['recipe_id'], ['recipes.recipe_id'], name='recipe_items_recipe_id_fkey'), + sa.PrimaryKeyConstraint('recipe_item_id', name='recipe_items_pkey'), + sa.UniqueConstraint('recipe_id', 'product_id', name='recipe_items_recipe_id_product_id_key') + ) + op.create_table('accounts', + sa.Column('id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('code', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('name', sa.VARCHAR(length=255), autoincrement=False, nullable=False), + sa.Column('type', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('account_type', sa.VARCHAR(length=50), autoincrement=False, nullable=False), + sa.Column('is_starred', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.Column('is_active', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.Column('is_reconcilable', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.Column('cost_centre_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('is_fixture', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['cost_centre_id'], ['cost_centres.CostCentreID'], name='accounts_cost_centre_id_fkey'), + sa.PrimaryKeyConstraint('id', name='accounts_pkey'), + sa.UniqueConstraint('name', name='accounts_name_key'), + postgresql_ignore_search_path=False + ) + op.create_table('product_groups', + sa.Column('ProductGroupID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Name', sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.Column('IsFixture', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.PrimaryKeyConstraint('ProductGroupID', name='entities_productgroups_pkey'), + sa.UniqueConstraint('Name', name='entities_productgroups_Name_key'), + postgresql_ignore_search_path=False + ) + op.create_table('attendances', + sa.Column('AttendanceID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('EmployeeID', postgresql.UUID(), autoincrement=False, nullable=True), + sa.Column('Date', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), + sa.Column('AttendanceType', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('Amount', sa.NUMERIC(), autoincrement=False, nullable=True), + sa.Column('CreationDate', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=True), + sa.Column('UserID', postgresql.UUID(), autoincrement=False, nullable=True), + sa.Column('IsValid', sa.BOOLEAN(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['EmployeeID'], ['employees.id'], name='entities_attendances_EmployeeID_fkey'), + sa.ForeignKeyConstraint(['UserID'], ['auth_users.UserID'], name='entities_attendances_UserID_fkey'), + sa.PrimaryKeyConstraint('AttendanceID', name='entities_attendances_pkey') + ) + op.create_table('cost_centres', + sa.Column('CostCentreID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Name', sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.Column('IsFixture', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.PrimaryKeyConstraint('CostCentreID', name='entities_costcenters_pkey'), + sa.UniqueConstraint('Name', name='entities_costcenters_Name_key'), + postgresql_ignore_search_path=False + ) + op.create_table('products', + sa.Column('ProductID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Code', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('Name', sa.VARCHAR(length=255), autoincrement=False, nullable=False), + sa.Column('Units', sa.VARCHAR(length=255), autoincrement=False, nullable=False), + sa.Column('Fraction', sa.NUMERIC(), autoincrement=False, nullable=False), + sa.Column('FractionUnits', sa.VARCHAR(length=255), autoincrement=False, nullable=False), + sa.Column('ProductYield', sa.NUMERIC(), autoincrement=False, nullable=False), + sa.Column('ProductGroupID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('account_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('cost_price', sa.NUMERIC(), autoincrement=False, nullable=False), + sa.Column('sale_price', sa.NUMERIC(), autoincrement=False, nullable=False), + sa.Column('IsActive', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.Column('IsFixture', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.Column('is_purchased', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.Column('is_sold', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['ProductGroupID'], ['product_groups.ProductGroupID'], name='products_ProductGroupID_fkey'), + sa.ForeignKeyConstraint(['account_id'], ['accounts.id'], name='products_account_id_fkey'), + sa.PrimaryKeyConstraint('ProductID', name='products_pkey'), + sa.UniqueConstraint('Code', name='products_Code_key'), + sa.UniqueConstraint('Name', 'Units', name='products_Name_Units_key'), + postgresql_ignore_search_path=False + ) + op.create_table('fingerprints', + sa.Column('FingerprintID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('EmployeeID', postgresql.UUID(), autoincrement=False, nullable=True), + sa.Column('Date', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['EmployeeID'], ['employees.id'], name='entities_fingerprints_EmployeeID_fkey'), + sa.PrimaryKeyConstraint('FingerprintID', name='entities_fingerprints_pkey'), + sa.UniqueConstraint('EmployeeID', 'Date', name='uq_employee_id_date') + ) + op.create_table('msg_threadtags', + sa.Column('ThreadTagID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('ThreadID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('TagID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['TagID'], ['msg_tags.TagID'], name='msg_threadtags_TagID_fkey'), + sa.ForeignKeyConstraint(['ThreadID'], ['msg_threads.ThreadID'], name='msg_threadtags_ThreadID_fkey'), + sa.PrimaryKeyConstraint('ThreadTagID', name='msg_threadtags_pkey'), + sa.UniqueConstraint('ThreadID', 'TagID', name='msg_threadtags_ThreadID_TagID_key') + ) + op.create_table('employees', + sa.Column('id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Designation', sa.VARCHAR(length=255), autoincrement=False, nullable=True), + sa.Column('Salary', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('ServicePoints', sa.NUMERIC(precision=5, scale=2), autoincrement=False, nullable=True), + sa.Column('JoiningDate', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), + sa.Column('LeavingDate', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['id'], ['accounts.id'], name='employees_id_fkey'), + sa.PrimaryKeyConstraint('id', name='entities_employees_pkey') + ) + op.create_table('inventories', + sa.Column('InventoryID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('VoucherID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('ProductID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('BatchID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('Quantity', sa.NUMERIC(), autoincrement=False, nullable=True), + sa.Column('Rate', sa.NUMERIC(), autoincrement=False, nullable=True), + sa.Column('Tax', sa.NUMERIC(), autoincrement=False, nullable=True), + sa.Column('Discount', sa.NUMERIC(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['BatchID'], ['batches.BatchID'], name='entities_inventories_BatchID_fkey'), + sa.ForeignKeyConstraint(['ProductID'], ['products.ProductID'], name='inventories_ProductID_fkey'), + sa.ForeignKeyConstraint(['VoucherID'], ['vouchers.VoucherID'], name='inventories_VoucherID_fkey'), + sa.PrimaryKeyConstraint('InventoryID', name='entities_inventories_pkey') + ) + op.create_index('ix_inventories_VoucherID', 'inventories', ['VoucherID'], unique=False) + op.create_table('auth_usergroups', + sa.Column('UserGroupID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('UserID', postgresql.UUID(), autoincrement=False, nullable=True), + sa.Column('GroupID', postgresql.UUID(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['GroupID'], ['auth_groups.GroupID'], name='auth_usergroups_GroupID_fkey'), + sa.ForeignKeyConstraint(['UserID'], ['auth_users.UserID'], name='auth_usergroups_UserID_fkey'), + sa.PrimaryKeyConstraint('UserGroupID', name='auth_usergroups_pkey') + ) + op.create_table('auth_clients', + sa.Column('client_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('code', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('name', sa.VARCHAR(length=255), autoincrement=False, nullable=False), + sa.Column('enabled', sa.BOOLEAN(), autoincrement=False, nullable=False), + sa.Column('otp', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('creation_date', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=False), + sa.PrimaryKeyConstraint('client_id', name='auth_clients_pkey'), + sa.UniqueConstraint('code', name='auth_clients_Code_key'), + sa.UniqueConstraint('name', name='auth_clients_Name_key') + ) + op.create_table('salary_deductions', + sa.Column('SalaryDeductionID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('VoucherID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('JournalID', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('GrossSalary', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('DaysWorked', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('EsiEmployee', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('PfEmployee', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('EsiEmployer', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('PfEmployer', sa.INTEGER(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['JournalID'], ['journals.JournalID'], name='entities_salarydeductions_JournalID_fkey'), + sa.ForeignKeyConstraint(['VoucherID'], ['vouchers.VoucherID'], name='salary_deductions_VoucherID_fkey'), + sa.PrimaryKeyConstraint('SalaryDeductionID', name='entities_salarydeductions_pkey') + ) + # ### end Alembic commands ### diff --git a/brewman/__init__.py b/brewman/__init__.py index f4b67eec..e69de29b 100644 --- a/brewman/__init__.py +++ b/brewman/__init__.py @@ -1,3 +0,0 @@ -def main(global_config, **settings): - SECRET_KEY = os.environ.get('SECRET_KEY', settings.get('secret_key', '')) - session_factory = SignedCookieSessionFactory(SECRET_KEY) diff --git a/brewman/config.py b/brewman/config.py index b61c2ea2..2034b3fd 100644 --- a/brewman/config.py +++ b/brewman/config.py @@ -9,4 +9,4 @@ class Settings: host: str = env("HOST") port: int = env.int("PORT") db_url: str = env("DB_URL") - log_level: str = env("LOG_LEVEL") \ No newline at end of file + log_level: str = env("LOG_LEVEL") diff --git a/brewman/core/security.py b/brewman/core/security.py index 8a4051c7..a6a2565d 100644 --- a/brewman/core/security.py +++ b/brewman/core/security.py @@ -15,6 +15,8 @@ from ..db.session import SessionLocal # to get a string like this run: # openssl rand -hex 32 +from ..schemas.auth import UserToken + SECRET_KEY = "8546a61262dab7c05ccf2e26abe30bc10966904df6dfd29259ea85dd0844a8e7" ALGORITHM = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES = 30 @@ -33,14 +35,6 @@ class TokenData(BaseModel): scopes: List[str] = [] -class User(BaseModel): - id_: uuid.UUID - name: str - locked_out: bool = None - password: str - permissions: List[str] - - def f7(seq): seen = set() seen_add = seen.add @@ -67,8 +61,8 @@ def create_access_token(*, data: dict, expires_delta: timedelta = None): return encoded_jwt -def get_user(username: str, id_: str, locked_out: bool, scopes: List[str]): - return User( +def get_user(username: str, id_: str, locked_out: bool, scopes: List[str]) -> UserToken: + return UserToken( id_=uuid.UUID(id_), name=username, locked_out=locked_out, @@ -87,7 +81,7 @@ def authenticate_user(username: str, password: str, db: Session) -> Union[UserMo async def get_current_user( security_scopes: SecurityScopes, token: str = Depends(oauth2_scheme), -): +) -> UserToken: if security_scopes.scopes: authenticate_value = f'Bearer scope="{security_scopes.scope_str}"' else: @@ -120,8 +114,8 @@ async def get_current_user( async def get_current_active_user( - current_user: User = Security(get_current_user, scopes=["authenticated"]) -): + current_user: UserToken = Security(get_current_user, scopes=["authenticated"]) +) -> UserToken: if current_user.locked_out: raise HTTPException(status_code=400, detail="Inactive user") return current_user diff --git a/brewman/db/base.py b/brewman/db/base.py index 61f24b72..b9a39c3a 100644 --- a/brewman/db/base.py +++ b/brewman/db/base.py @@ -7,8 +7,8 @@ from brewman.models import ( role_group, User, LoginHistory, - Group, Role, + Permission, Product, AttendanceType, CostCentre, diff --git a/brewman/main.py b/brewman/main.py index 6d2814bd..514ff2aa 100644 --- a/brewman/main.py +++ b/brewman/main.py @@ -16,7 +16,7 @@ from .routers import ( recipe, login ) -from .routers.auth import client, user, group +from .routers.auth import client, user, role from .db.base_class import Base from .config import Settings as settings from .db.session import SessionLocal, engine @@ -43,8 +43,9 @@ app.include_router(product_group.router, prefix="/api/product-groups", tags=["pr app.include_router(recipe.router, prefix="/api/recipes", tags=["products"]) app.include_router(client.router, prefix="/api/clients", tags=["users"]) -app.include_router(group.router, prefix="/api/groups", tags=["users"]) +app.include_router(role.router, prefix="/api/roles", tags=["users"]) app.include_router(user.router, prefix="/api/users", tags=["users"]) + def init(): uvicorn.run(app, host=settings.host, port=settings.port) diff --git a/brewman/models/__init__.py b/brewman/models/__init__.py index a288de16..47db3dc7 100644 --- a/brewman/models/__init__.py +++ b/brewman/models/__init__.py @@ -1,17 +1,11 @@ -from sqlalchemy import engine_from_config -from sqlalchemy.orm import sessionmaker -from sqlalchemy.orm import configure_mappers - -# import or define all models here to ensure they are attached to the -# Base.metadata prior to any initialization routines from .auth import ( Client, - user_group, - role_group, + user_role, + role_permission, User, LoginHistory, - Group, - Role + Role, + Permission ) from .master import ( Product, @@ -36,67 +30,3 @@ from .voucher import ( Voucher, VoucherType, ) - -# run configure_mappers after defining all of the models to ensure -# all relationships can be setup -configure_mappers() - - -def get_engine(settings, prefix="sqlalchemy."): - return engine_from_config(settings, prefix) - - -def get_session_factory(engine): - factory = sessionmaker(expire_on_commit=False) - factory.configure(bind=engine) - return factory - - -def get_tm_session(session_factory, transaction_manager): - """ - Get a ``sqlalchemy.orm.Session`` instance backed by a transaction. - - This function will hook the session to the transaction manager which - will take care of committing any changes. - - - When using pyramid_tm it will automatically be committed or aborted - depending on whether an exception is raised. - - - When using scripts you should wrap the session in a manager yourself. - For example:: - - import transaction - - engine = get_engine(settings) - session_factory = get_session_factory(engine) - with transaction.manager: - dbsession = get_tm_session(session_factory, transaction.manager) - - """ - dbsession = session_factory() - zope.sqlalchemy.register(dbsession, transaction_manager=transaction_manager) - return dbsession - - -def includeme(config): - """ - Initialize the model for a Pyramid app. - - Activate this setup using ``config.include('.models')``. - - """ - settings = config.get_settings() - - # use pyramid_tm to hook the transaction lifecycle to the request - config.include("pyramid_tm") - - session_factory = get_session_factory(get_engine(settings)) - config.registry["dbsession_factory"] = session_factory - - # make request.dbsession available for use in Pyramid - config.add_request_method( - # r.tm is the transaction manager used by pyramid_tm - lambda r: get_tm_session(session_factory, r.tm), - "dbsession", - reify=True, - ) diff --git a/brewman/models/auth.py b/brewman/models/auth.py index f168db39..8b63cafa 100644 --- a/brewman/models/auth.py +++ b/brewman/models/auth.py @@ -60,32 +60,32 @@ class Client(Base): return client -user_group = Table( - "auth_usergroups", +user_role = Table( + "user_roles", Base.metadata, - Column("UserGroupID", GUID(), primary_key=True, default=uuid.uuid4), - Column("UserID", GUID(), ForeignKey("auth_users.UserID")), - Column("GroupID", GUID(), ForeignKey("auth_groups.GroupID")), + Column("id", GUID(), primary_key=True, default=uuid.uuid4), + Column("user_id", GUID(), ForeignKey("auth_users.id")), + Column("role_id", GUID(), ForeignKey("auth_roles.id")), ) -role_group = Table( - "auth_rolegroups", +role_permission = Table( + "role_permissions", Base.metadata, - Column("RoleGroupID", GUID(), primary_key=True, default=uuid.uuid4), - Column("RoleID", GUID(), ForeignKey("auth_roles.RoleID")), - Column("GroupID", GUID(), ForeignKey("auth_groups.GroupID")), + Column("id", GUID(), primary_key=True, default=uuid.uuid4), + Column("permission_id", GUID(), ForeignKey("auth_permissions.id")), + Column("role_id", GUID(), ForeignKey("auth_roles.id")), ) class User(Base): __tablename__ = "auth_users" - id = Column("UserID", GUID(), primary_key=True, default=uuid.uuid4) - name = Column("Name", Unicode(255), unique=True) - _password = Column("Password", Unicode(60)) - locked_out = Column("LockedOut", Boolean) + id_ = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + name = Column("username", Unicode(255), unique=True) + _password = Column("password", Unicode(60)) + locked_out = Column("disabled", Boolean) - groups = relationship("Group", secondary=user_group) + roles = relationship("Role", secondary=user_role) login_history = relationship("LoginHistory", backref="user") def _get_password(self): @@ -101,17 +101,17 @@ class User(Base): def __name__(self): return self.name - def __init__(self, name=None, password=None, locked_out=None, id=None): + def __init__(self, name=None, password=None, locked_out=None, id_=None): self.name = name self.password = password self.locked_out = locked_out - self.id = id + self.id_ = id_ @classmethod - def auth(cls, name, password, dbsession) -> (bool, any): + def auth(cls, name, password, db) -> (bool, any): if password is None: return False, None - user = dbsession.query(User).filter(User.name.ilike(name)).first() + user = db.query(User).filter(User.name.ilike(name)).first() if not user: return False, None if user.password != encrypt(password) or user.locked_out: @@ -124,7 +124,7 @@ class LoginHistory(Base): __tablename__ = "auth_login_history" __table_args__ = (UniqueConstraint("user_id", "client_id", "date"),) id = Column("login_history_id", GUID(), primary_key=True, default=uuid.uuid4) - user_id = Column("user_id", GUID(), ForeignKey("auth_users.UserID"), nullable=False) + user_id = Column("user_id", GUID(), ForeignKey("auth_users.id"), nullable=False) client_id = Column( "client_id", GUID(), ForeignKey("auth_clients.client_id"), nullable=False ) @@ -137,25 +137,25 @@ class LoginHistory(Base): self.id = id -class Group(Base): - __tablename__ = "auth_groups" - - id = Column("GroupID", GUID(), primary_key=True, default=uuid.uuid4) - name = Column("Name", Unicode(255), unique=True) - - def __init__(self, name=None, id=None): - self.name = name - self.id = id - - class Role(Base): __tablename__ = "auth_roles" - id = Column("RoleID", GUID(), primary_key=True, default=uuid.uuid4) - name = Column("Name", Unicode(255), unique=True) + id_ = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + name = Column("name", Unicode(255), unique=True) - groups = relationship("Group", secondary=role_group, backref="roles") - - def __init__(self, name=None, id=None): + def __init__(self, name=None, id_=None): self.name = name - self.id = id + self.id_ = id_ + + +class Permission(Base): + __tablename__ = "auth_permissions" + + id_ = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + name = Column("name", Unicode(255), unique=True) + + roles = relationship("Role", secondary=role_permission, backref="permissions") + + def __init__(self, name=None, id_=None): + self.name = name + self.id_ = id_ diff --git a/brewman/models/master.py b/brewman/models/master.py index 69539170..3ad13218 100644 --- a/brewman/models/master.py +++ b/brewman/models/master.py @@ -22,26 +22,26 @@ from .meta import Base class Product(Base): __tablename__ = "products" - __table_args__ = (UniqueConstraint("Name", "Units"),) + __table_args__ = (UniqueConstraint("name", "units"),) - id = Column("ProductID", GUID(), primary_key=True, default=uuid.uuid4) - code = Column("Code", Integer, unique=True) - name = Column("Name", Unicode(255), nullable=False) - units = Column("Units", Unicode(255), nullable=False) - fraction = Column("Fraction", Numeric, nullable=False) - fraction_units = Column("FractionUnits", Unicode(255), nullable=False) - product_yield = Column("ProductYield", Numeric, nullable=False) + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + code = Column("code", Integer, unique=True) + name = Column("name", Unicode(255), nullable=False) + units = Column("units", Unicode(255), nullable=False) + fraction = Column("fraction", Numeric, nullable=False) + fraction_units = Column("fraction_units", Unicode(255), nullable=False) + product_yield = Column("product_yield", Numeric, nullable=False) product_group_id = Column( - "ProductGroupID", + "product_group_id", GUID(), - ForeignKey("product_groups.ProductGroupID"), + ForeignKey("product_groups.id"), nullable=False, ) account_id = Column("account_id", GUID(), ForeignKey("accounts.id"), nullable=False) price = Column("cost_price", Numeric, nullable=False) sale_price = Column("sale_price", Numeric, nullable=False) - is_active = Column("IsActive", Boolean, nullable=False) - is_fixture = Column("IsFixture", Boolean, nullable=False) + is_active = Column("is_active", Boolean, nullable=False) + is_fixture = Column("is_fixture", Boolean, nullable=False) is_purchased = Column("is_purchased", Boolean, nullable=False) is_sold = Column("is_sold", Boolean, nullable=False) @@ -101,10 +101,7 @@ class Product(Base): def can_delete(self, advanced_delete): if self.is_fixture: - return ( - False, - "{0} is a fixture and cannot be edited or deleted.".format(self.name), - ) + return False, f"{self.name} is a fixture and cannot be edited or deleted." if self.is_active: return False, "Product is active" if len(self.inventories) > 0 and not advanced_delete: @@ -131,10 +128,8 @@ class Product(Base): class Recipe(Base): __tablename__ = "recipes" - id = Column("recipe_id", GUID(), primary_key=True, default=uuid.uuid4) - product_id = Column( - "product_id", GUID(), ForeignKey("products.ProductID"), nullable=False - ) + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + product_id = Column("product_id", GUID(), ForeignKey("products.id"), nullable=False) quantity = Column("quantity", Numeric, nullable=False) cost_price = Column("cost_price", Numeric, nullable=False) @@ -179,11 +174,8 @@ class RecipeItem(Base): id = Column("recipe_item_id", GUID(), primary_key=True, default=uuid.uuid4) recipe_id = Column( - "recipe_id", GUID(), ForeignKey("recipes.recipe_id"), nullable=False - ) - product_id = Column( - "product_id", GUID(), ForeignKey("products.ProductID"), nullable=False - ) + "recipe_id", GUID(), ForeignKey("recipes.id"), nullable=False) + product_id = Column("product_id", GUID(), ForeignKey("products.id"), nullable=False) quantity = Column("quantity", Integer, nullable=False) price = Column("price", Integer, nullable=False) @@ -202,9 +194,9 @@ class RecipeItem(Base): class ProductGroup(Base): __tablename__ = "product_groups" - id = Column("ProductGroupID", GUID(), primary_key=True, default=uuid.uuid4) - name = Column("Name", Unicode(255), unique=True) - is_fixture = Column("IsFixture", Boolean, nullable=False) + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + name = Column("name", Unicode(255), unique=True) + is_fixture = Column("is_fixture", Boolean, nullable=False) products = relationship("Product", backref="product_group") @@ -225,9 +217,9 @@ class ProductGroup(Base): class CostCentre(Base): __tablename__ = "cost_centres" - id = Column("CostCentreID", GUID(), primary_key=True, default=uuid.uuid4) - name = Column("Name", Unicode(255), unique=True) - is_fixture = Column("IsFixture", Boolean, nullable=False) + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + name = Column("name", Unicode(255), unique=True) + is_fixture = Column("is_fixture", Boolean, nullable=False) accounts = relationship("AccountBase", backref="cost_centre") journals = relationship("Journal", backref="cost_centre") @@ -272,12 +264,7 @@ class AccountBase(Base): is_starred = Column("is_starred", Boolean, nullable=False) is_active = Column("is_active", Boolean, nullable=False) is_reconcilable = Column("is_reconcilable", Boolean, nullable=False) - cost_centre_id = Column( - "cost_centre_id", - GUID(), - ForeignKey("cost_centres.CostCentreID"), - nullable=False, - ) + cost_centre_id = Column("cost_centre_id", GUID(), ForeignKey("cost_centres.id"), nullable=False) is_fixture = Column("is_fixture", Boolean, nullable=False) __mapper_args__ = {"polymorphic_on": account_type} diff --git a/brewman/models/voucher.py b/brewman/models/voucher.py index 30369975..f41bde40 100644 --- a/brewman/models/voucher.py +++ b/brewman/models/voucher.py @@ -62,7 +62,7 @@ class VoucherType: class Voucher(Base): __tablename__ = "vouchers" - id = Column("VoucherID", GUID(), primary_key=True, default=uuid.uuid4) + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) date = Column("date", DateTime, nullable=False, index=True) narration = Column("narration", Unicode(1000), nullable=False) is_reconciled = Column("is_reconciled", Boolean, nullable=False) @@ -71,9 +71,9 @@ class Voucher(Base): creation_date = Column("creation_date", DateTime(timezone=True), nullable=False) last_edit_date = Column("last_edit_date", DateTime(timezone=True), nullable=False) _type = Column("voucher_type", Integer, nullable=False) - user_id = Column("user_id", GUID(), ForeignKey("auth_users.UserID"), nullable=False) + user_id = Column("user_id", GUID(), ForeignKey("auth_users.id"), nullable=False) posted = Column("is_posted", Boolean, nullable=False) - poster_id = Column("poster_id", GUID(), ForeignKey("auth_users.UserID")) + poster_id = Column("poster_id", GUID(), ForeignKey("auth_users.id")) user = relationship("User", primaryjoin="User.id==Voucher.user_id", cascade=None) poster = relationship( @@ -160,20 +160,12 @@ class Voucher(Base): class Journal(Base): __tablename__ = "journals" - id = Column("JournalID", GUID(), primary_key=True, default=uuid.uuid4) - debit = Column("Debit", Integer) - amount = Column("Amount", Numeric) - voucher_id = Column( - "VoucherID", - GUID(), - ForeignKey("vouchers.VoucherID"), - nullable=False, - index=True, - ) + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + debit = Column("debit", Integer) + amount = Column("amount", Numeric) + voucher_id = Column("voucher_id", GUID(), ForeignKey("vouchers.id"), nullable=False, index=True) account_id = Column("account_id", GUID(), ForeignKey("accounts.id"), nullable=False) - cost_centre_id = Column( - "CostCentreID", GUID(), ForeignKey("cost_centres.CostCentreID"), nullable=False - ) + cost_centre_id = Column("cost_centre_id", GUID(), ForeignKey("cost_centres.id"), nullable=False) @hybrid_property def signed_amount(self): @@ -202,19 +194,15 @@ class Journal(Base): class SalaryDeduction(Base): __tablename__ = "salary_deductions" - id = Column("SalaryDeductionID", GUID(), primary_key=True, default=uuid.uuid4) - voucher_id = Column( - "VoucherID", GUID(), ForeignKey("vouchers.VoucherID"), nullable=False - ) - journal_id = Column( - "JournalID", GUID(), ForeignKey("journals.JournalID"), nullable=False - ) - gross_salary = Column("GrossSalary", Integer) - days_worked = Column("DaysWorked", Integer) - esi_ee = Column("EsiEmployee", Integer) - pf_ee = Column("PfEmployee", Integer) - esi_er = Column("EsiEmployer", Integer) - pf_er = Column("PfEmployer", Integer) + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + voucher_id = Column("voucher_id", GUID(), ForeignKey("vouchers.id"), nullable=False) + journal_id = Column("journal_id", GUID(), ForeignKey("journals.id"), nullable=False) + gross_salary = Column("gross_salary", Integer) + days_worked = Column("days_worked", Integer) + esi_ee = Column("esi_employee", Integer) + pf_ee = Column("pf_employee", Integer) + esi_er = Column("esi_employer", Integer) + pf_er = Column("pf_employer", Integer) journal = relationship( Journal, @@ -253,10 +241,10 @@ class ServiceCharge(Base): __tablename__ = "service_charges" id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) voucher_id = Column( - "voucher_id", GUID(), ForeignKey("vouchers.VoucherID"), nullable=False + "voucher_id", GUID(), ForeignKey("vouchers.id"), nullable=False ) journal_id = Column( - "journal_id", GUID(), ForeignKey("journals.JournalID"), nullable=False + "journal_id", GUID(), ForeignKey("journals.id"), nullable=False ) days_worked = Column("days_worked", Integer, nullable=False) points = Column("points", Numeric(precision=5, scale=2), nullable=False) @@ -288,23 +276,15 @@ class ServiceCharge(Base): class Inventory(Base): __tablename__ = "inventories" - __table_args__ = (UniqueConstraint("VoucherID", "BatchID"),) - id = Column("InventoryID", GUID(), primary_key=True, default=uuid.uuid4) - voucher_id = Column( - "VoucherID", - GUID(), - ForeignKey("vouchers.VoucherID"), - nullable=False, - index=True, - ) - product_id = Column( - "ProductID", GUID(), ForeignKey("products.ProductID"), nullable=False - ) - batch_id = Column("BatchID", GUID(), ForeignKey("batches.BatchID"), nullable=False) - quantity = Column("Quantity", Numeric) - rate = Column("Rate", Numeric) - tax = Column("Tax", Numeric) - discount = Column("Discount", Numeric) + __table_args__ = (UniqueConstraint("voucher_id", "batch_id"),) + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + voucher_id = Column("voucher_id", GUID(), ForeignKey("vouchers.id"), nullable=False, index=True) + product_id = Column("product_id", GUID(), ForeignKey("products.id"), nullable=False) + batch_id = Column("batch_id", GUID(), ForeignKey("batches.id"), nullable=False) + quantity = Column("quantity", Numeric) + rate = Column("rate", Numeric) + tax = Column("tax", Numeric) + discount = Column("discount", Numeric) def __init__( self, @@ -337,15 +317,13 @@ class Inventory(Base): class Batch(Base): __tablename__ = "batches" - id = Column("BatchID", GUID(), primary_key=True, default=uuid.uuid4) - name = Column("Name", DateTime) - product_id = Column( - "ProductID", GUID(), ForeignKey("products.ProductID"), nullable=False - ) - quantity_remaining = Column("QuantityRemaining", Numeric) - rate = Column("Rate", Numeric) - tax = Column("Tax", Numeric) - discount = Column("Discount", Numeric) + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + name = Column("name", DateTime) + product_id = Column("product_id", GUID(), ForeignKey("products.id"), nullable=False) + quantity_remaining = Column("quantity_remaining", Numeric) + rate = Column("rate", Numeric) + tax = Column("tax", Numeric) + discount = Column("discount", Numeric) inventories = relationship( "Inventory", backref="batch", cascade=None, cascade_backrefs=False @@ -391,14 +369,14 @@ class Batch(Base): class Attendance(Base): __tablename__ = "attendances" - id = Column("AttendanceID", GUID(), primary_key=True, default=uuid.uuid4) - employee_id = Column("EmployeeID", GUID(), ForeignKey("employees.id")) - date = Column("Date", DateTime) - attendance_type = Column("AttendanceType", Integer) - amount = Column("Amount", Numeric) - creation_date = Column("CreationDate", DateTime(timezone=True)) - user_id = Column("UserID", GUID(), ForeignKey("auth_users.UserID")) - is_valid = Column("IsValid", Boolean) + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + employee_id = Column("employee_id", GUID(), ForeignKey("employees.id")) + date = Column("date", DateTime) + attendance_type = Column("attendance_type", Integer) + amount = Column("amount", Numeric) + creation_date = Column("creation_date", DateTime(timezone=True)) + user_id = Column("user_id", GUID(), ForeignKey("auth_users.id")) + is_valid = Column("is_valid", Boolean) user = relationship("User", primaryjoin="User.id==Attendance.user_id") @@ -441,9 +419,9 @@ class Attendance(Base): class Fingerprint(Base): __tablename__ = "fingerprints" - id = Column("FingerprintID", GUID(), primary_key=True, default=uuid.uuid4) - employee_id = Column("EmployeeID", GUID(), ForeignKey("employees.id")) - date = Column("Date", DateTime) + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + employee_id = Column("employee_id", GUID(), ForeignKey("employees.id")) + date = Column("date", DateTime) def __init__(self, id=None, employee_id=None, date=None): self.id = id diff --git a/brewman/routers/account.py b/brewman/routers/account.py index b9186d69..e9b245a8 100644 --- a/brewman/routers/account.py +++ b/brewman/routers/account.py @@ -8,7 +8,8 @@ from sqlalchemy import func from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm import joinedload_all, Session -from ..core.security import User, get_current_active_user as get_user +from ..schemas.auth import UserToken +from ..core.security import get_current_active_user as get_user from ..db.session import SessionLocal from ..models.master import CostCentre, Account, AccountType, AccountBase from ..models.voucher import Voucher, Journal, VoucherType @@ -30,7 +31,7 @@ def get_db(): def save( data: schemas.AccountIn, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["accounts"]), + user: UserToken = Security(get_user, scopes=["accounts"]), ): try: item = Account( @@ -62,7 +63,7 @@ def update( id_: uuid.UUID, data: schemas.AccountIn, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["accounts"]), + user: UserToken = Security(get_user, scopes=["accounts"]), ): try: item: Account = db.query(Account).filter(Account.id == id_).first() @@ -98,10 +99,10 @@ def update( def delete( id_: uuid.UUID, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["accounts"]), + user: UserToken = Security(get_user, scopes=["accounts"]), ): account: Account = db.query(Account).filter(Account.id == id_).first() - can_delete, reason = account.can_delete("Advanced Delete" in user.permissions) + can_delete, reason = account.can_delete("advanced-delete" in user.permissions) if can_delete: delete_with_data(account, db) db.commit() @@ -116,13 +117,13 @@ def delete( @router.get("/") def show_blank( - db: Session = Depends(get_db), user: User = Security(get_user, scopes=["accounts"]) + db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["accounts"]) ): return account_info(None, db) @router.get("/list") -async def show_list(db: Session = Depends(get_db), user: User = Depends(get_user)): +async def show_list(db: Session = Depends(get_db), user: UserToken = Depends(get_user)): return [ { "id": item.id, @@ -146,7 +147,7 @@ async def show_term( a: bool = None, c: int = None, db: Session = Depends(get_db), - current_user: User = Depends(get_user), + current_user: UserToken = Depends(get_user), ): count = c @@ -163,7 +164,7 @@ async def show_balance( id_: uuid.UUID, d: str = None, db: Session = Depends(get_db), - user: User = Depends(get_user), + user: UserToken = Depends(get_user), ): date = None if d is None or d == "" else datetime.datetime.strptime(d, "%d-%b-%Y") return {"date": balance(id_, date, db), "total": balance(id_, None, db)} @@ -173,7 +174,7 @@ async def show_balance( def show_id( id_: uuid.UUID, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["accounts"]), + user: UserToken = Security(get_user, scopes=["accounts"]), ): return account_info(id_, db) diff --git a/brewman/routers/account_types.py b/brewman/routers/account_types.py index 7f5bc5e8..47b65a59 100644 --- a/brewman/routers/account_types.py +++ b/brewman/routers/account_types.py @@ -1,13 +1,14 @@ from fastapi import APIRouter, Depends -from ..core.security import User, get_current_active_user as get_user +from ..schemas.auth import UserToken +from ..core.security import get_current_active_user as get_user from brewman.models.master import AccountType router = APIRouter() @router.get("/") -def account_type_list(user: User = Depends(get_user)): +def account_type_list(user: UserToken = Depends(get_user)): return [ {"id": item.id, "name": item.name} for item in AccountType.list() diff --git a/brewman/routers/attendance.py b/brewman/routers/attendance.py index d2e54c4d..ec0f6451 100644 --- a/brewman/routers/attendance.py +++ b/brewman/routers/attendance.py @@ -5,12 +5,13 @@ from sqlalchemy import or_ from sqlalchemy.orm import Session from fastapi import Depends, Security +from ..schemas.auth import UserToken from ..models.master import Employee from ..models.voucher import Attendance from ..routers.fingerprint import get_prints from ..routers.services.session import session_current_date from ..db.session import SessionLocal -from ..core.security import User, get_current_active_user as get_user +from ..core.security import get_current_active_user as get_user from fastapi import APIRouter @@ -27,7 +28,7 @@ def get_db(): @router.get("/") -def attendance_blank(db: Session = Depends(get_db), user: User = Security(get_user, scopes=["attendance"])): +def attendance_blank(db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["attendance"])): return {"date": session_current_date(request), "body": []} diff --git a/brewman/routers/auth/group.py b/brewman/routers/auth/group.py deleted file mode 100644 index 73e52679..00000000 --- a/brewman/routers/auth/group.py +++ /dev/null @@ -1,93 +0,0 @@ -import uuid -from brewman.models.auth import Group, Role - -from fastapi import APIRouter - -router = APIRouter() - - -@router.post("/new") # "Users" -def save(request): - group = Group(request.json_body["name"]) - request.dbsession.add(group) - add_permissions(group, request.json_body["permissions"], request.dbsession) - transaction.commit() - return group_info(group.id, request.dbsession) - - -@router.put("/{id}") # "Users" -def update(request): - id_ = request.matchdict.get("id", None) - group = request.dbsession.query(Group).filter(Group.id == uuid.UUID(id_)).one() - group.name = request.json_body["name"] - add_permissions(group, request.json_body["permissions"], request.dbsession) - transaction.commit() - return group_info(group.id, request.dbsession) - - -def add_permissions(group, permissions, dbsession): - for permission in permissions: - id_ = uuid.UUID(permission["id"]) - gp = [p for p in group.roles if p.id == id_] - gp = None if len(gp) == 0 else gp[0] - if permission["enabled"] and gp is None: - group.roles.append(dbsession.query(Role).filter(Role.id == id_).one()) - elif not permission["enabled"] and gp: - group.roles.remove(gp) - - -@router.delete("/{id}") # "Users" -def delete(request): - id_ = request.matchdict.get("id", None) - if id_ is None: - response = Response("Group is Null") - response.status_int = 500 - return response - else: - response = Response("Group deletion not implemented") - response.status_int = 500 - return response - - -@router.get("/{id}") # "Users" -def show_id(request): - return group_info(uuid.UUID(request.matchdict.get("id", None)), request.dbsession) - - -@router.get("/new") # "Users" -def show_blank(request): - return group_info(None, request.dbsession) - - -@router.get("/") # "Users" -async def show_list(l: bool): - list_ = request.dbsession.query(Group).order_by(Group.name).all() - - groups = [] - for item in list_: - group = {"id": item.id, "name": item.name, "permissions": []} - for permission in sorted(item.roles, key=lambda p: p.name): - group["permissions"].append(permission.name) - groups.append(group) - return groups - - -def group_info(id_, dbsession): - if id_ is None: - group = {"name": "", "permissions": []} - for item in dbsession.query(Role).order_by(Role.name).all(): - group["permissions"].append( - {"id": item.id, "name": item.name, "enabled": False} - ) - else: - group_object = dbsession.query(Group).filter(Group.id == id_).one() - group = {"id": group_object.id, "name": group_object.name, "permissions": []} - for item in dbsession.query(Role).order_by(Role.name).all(): - group["permissions"].append( - { - "id": item.id, - "name": item.name, - "enabled": True if item in group_object.roles else False, - } - ) - return group diff --git a/brewman/routers/auth/role.py b/brewman/routers/auth/role.py new file mode 100644 index 00000000..67d3e501 --- /dev/null +++ b/brewman/routers/auth/role.py @@ -0,0 +1,163 @@ +import traceback +import uuid +from typing import List, Optional + +from fastapi import APIRouter, HTTPException, status, Depends, Security +from sqlalchemy.exc import SQLAlchemyError +from sqlalchemy.orm import Session + +from ...schemas.auth import UserToken +from ...core.security import get_current_active_user as get_user +from ...db.session import SessionLocal +from ...models.auth import Role, Permission +import brewman.schemas.auth as schemas + +router = APIRouter() + + +# Dependency +def get_db(): + try: + db = SessionLocal() + yield db + finally: + db.close() + + +@router.post("/", response_model=schemas.Role) +def save( + data: schemas.RoleIn, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["users"]), +): + try: + item = Role(data.name) + db.add(item) + add_permissions(item, data.permissions, db) + db.commit() + return role_info(item, db) + except SQLAlchemyError as e: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=str(e), + ) + except Exception: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=traceback.format_exc(), + ) + + +@router.put("/{id_}", response_model=schemas.Role) +def update( + id_: uuid.UUID, + data: schemas.RoleIn, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["users"]), +): + try: + item: Role = db.query(Role).filter(Role.id == id_).first() + item.name = data.name + add_permissions(item, data.permissions, db) + db.commit() + return role_info(item, db) + except SQLAlchemyError as e: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=str(e), + ) + except Exception: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=traceback.format_exc(), + ) + + +def add_permissions(group: Role, permissions: List[schemas.PermissionItem], db): + for permission in permissions: + gp = [p for p in group.roles if p.id == permission.id_] + gp = None if len(gp) == 0 else gp[0] + if permission.enabled and gp is None: + group.roles.append(db.query(Role).filter(Role.id == permission.id_).one()) + elif not permission.enabled and gp: + group.roles.remove(gp) + + +@router.delete("/{id_}") +def delete( + id_: uuid.UUID, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["users"]), +): + try: + item: Role = db.query(Role).filter(Role.id == id_).first() + if item is None: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Role not found", + ) + else: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Role deletion not implemented", + ) + except Exception: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=traceback.format_exc(), + ) + + +@router.get("/") +def show_blank( + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["users"]), +): + return role_info(None, db) + + +@router.get("/list", response_model=List[schemas.RoleList]) +async def show_list(db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["users"])): + return [ + {"id": item.id, "name": item.name, "permissions": [p.name for p in sorted(item.roles, key=lambda p: p.name)]} + for item in db.query(Role).order_by(Role.name).all() + ] + + +@router.get("/{id_}", response_model=schemas.Role) +def show_id( + id_: uuid.UUID, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["users"]), +): + item = db.query(Role).filter(Role.id == id_).first() + return role_info(item, db) + + +def role_info(item: Optional[Role], db): + if item is None: + return { + "name": "", + "permissions": [ + {"id": p.id, "name": p.name, "enabled": False} + for p in db.query(Permission).order_by(Permission.name).all() + ] + } + else: + return { + "id": item.id_, + "name": item.name, + "permissions": [ + { + "id": item.id, + "name": item.name, + "enabled": True if item in item.roles else False, + } + for item in db.query(Role).order_by(Role.name).all() + ] + } diff --git a/brewman/routers/auth/user.py b/brewman/routers/auth/user.py index 61eb547e..a0228d9a 100644 --- a/brewman/routers/auth/user.py +++ b/brewman/routers/auth/user.py @@ -1,179 +1,220 @@ -import re +import traceback import uuid -from brewman.models.auth import User, Group -from brewman.models.validation_exception import ValidationError +from typing import List, Optional -from fastapi import APIRouter +from fastapi import APIRouter, HTTPException, status, Depends, Security +from sqlalchemy.exc import SQLAlchemyError +from sqlalchemy.orm import Session + +from ...schemas.auth import UserToken +from ...core.security import get_current_active_user as get_user +from ...db.session import SessionLocal +from brewman.models.auth import User, Role +import brewman.schemas.auth as schemas router = APIRouter() -class UserView(object): - def __init__(self, request): - self.request = request - self.user = request.authenticated_userid - self.permissions = None - if self.user is not None: - self.user = ( - request.dbsession.query(User) - .filter(User.id == request.authenticated_userid) - .one() - ) +# Dependency +def get_db(): + try: + db = SessionLocal() + yield db + finally: + db.close() - @router.post("/new") # "Users" - def save(self): - return self.save_user() - def save_user(self): - user = User( - self.request.json_body["name"], - self.request.json_body["password"], - self.request.json_body["lockedOut"], +@router.post("/", response_model=schemas.User) +def save( + data: schemas.UserIn, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["users"]), +): + try: + item = User( + name=data.name, + password=data.password, + locked_out=data.locked_out ) - self.request.dbsession.add(user) - self.add_groups(user, self.request.json_body["groups"]) - transaction.commit() - return self.user_info(user.id) - - @router.put("/{id}") # "Authenticated" - def update(self): - id_ = self.request.matchdict["id"] - p = re.compile( - "^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$" + db.add(item) + add_roles(item, data.roles, db) + db.commit() + return user_info(item, db, user) + except SQLAlchemyError as e: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=str(e), ) - if p.match(id_): - user = ( - self.request.dbsession.query(User) - .filter(User.id == uuid.UUID(id_)) - .one() + except Exception: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=traceback.format_exc(), + ) + + +@router.get("/me", response_model=schemas.Role) +def show_me( + id_: uuid.UUID, + db: Session = Depends(get_db), + user: User = Depends(get_user), +): + item = db.query(Role).filter(Role.id_ == id_).first() + return user_info(item, db, user) + + +@router.put("/me", response_model=schemas.User) +def update_me( + id_: uuid.UUID, + data: schemas.UserIn, + db: Session = Depends(get_db), + user: User = Depends(get_user), +): + try: + item: User = db.query(User).filter(User.id_ == id_).first() + if "advanced-delete" in user.permissions: + item.name = data.name + item.locked_out = data.locked_out + add_roles(item, data.roles, db) + if data.password and item.password != data.password: + item.password = data.password + db.commit() + return user_info(item, db, user) + except SQLAlchemyError as e: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=str(e), + ) + except Exception: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=traceback.format_exc(), + ) + + +@router.put("/{id_}", response_model=schemas.User) +def update( + id_: uuid.UUID, + data: schemas.UserIn, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["users"]), +): + try: + item: User = db.query(User).filter(User.id_ == id_).first() + item.name = data.name + if data.password and item.password != data.password: + item.password = data.password + item.locked_out = data.locked_out + add_roles(item, data.roles, db) + db.commit() + return user_info(item, db, user) + except SQLAlchemyError as e: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=str(e), + ) + except Exception: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=traceback.format_exc(), + ) + + +def add_roles(user: User, roles: List[schemas.RoleItem], db: Session): + for role in roles: + ug = [g for g in user.roles if g.id_ == role.id_] + ug = None if len(ug) == 0 else ug[0] + if role.enabled and ug is None: + user.roles.append(db.query(Role).filter(Role.id_ == role.id_).one()) + elif not role.enabled and ug: + user.roles.remove(ug) + + +@router.delete("/{id_}") +def delete( + id_: uuid.UUID, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["users"]), +): + try: + item: Role = db.query(Role).filter(Role.id_ == id_).first() + if item is None: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="User not found", ) else: - user = ( - self.request.dbsession.query(User).filter(User.name.ilike(id_)).first() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="User deletion not implemented", ) - return self.update_user(user) - - def update_user(self, user): - if user is None: - raise ValidationError("User name / id not found") - if self.request.has_permission("Users"): - user.name = self.request.json_body["name"] - user.locked_out = self.request.json_body["lockedOut"] - self.add_groups(user, self.request.json_body["groups"]) - - if ( - self.request.json_body["password"] != "" - and self.request.json_body["password"] != user.password - ): - user.password = self.request.json_body["password"] - transaction.commit() - return self.user_info(user.id) - - @router.delete("/{id}") # "Users" - def delete(self): - id_ = self.request.matchdict.get("id", None) - if id_ is None: - response = Response("User is Null") - response.status_int = 500 - return response - else: - response = Response("User deletion not implemented") - response.status_int = 500 - return response - - @router.get("/{id}") # "Authenticated" - def show_id(self): - id_ = self.request.matchdict["id"] - p = re.compile( - "^[A-Za-z0-9]{8}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{12}$" + except Exception: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=traceback.format_exc(), ) - if p.match(id_): - id_ = uuid.UUID(id_) - return self.user_info(id_) - @router.get("/new") # "Users" - def show_blank(self): - return self.user_info(None) - @router.get("/") # "Users" - async def show_list(l: bool): - list_ = self.request.dbsession.query(User).order_by(User.name).all() - users = [] - for item in list_: - user = { - "name": item.name, - "lockedOut": item.locked_out, - "groups": [g.name for g in item.groups], - } - users.append(user) - return users +@router.get("/") +def show_blank( + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["users"]), +): + return user_info(None, db, user) - @router.get("/") # "Authenticated" - async def show_name(n: bool): - list_ = ( - self.request.dbsession.query(User) - .filter(User.locked_out == False) - .order_by(User.name) - .all() - ) - users = [{"name": item.name} for item in list_] - return users - def user_info(self, id_): - if id_ is None: - account = {"name": "", "lockedOut": False, "lockedOut": False, "groups": []} - for item in self.request.dbsession.query(Group).order_by(Group.name).all(): - account["groups"].append( - {"id": item.id, "name": item.name, "enabled": False} - ) - return account +@router.get("/list", response_model=List[schemas.UserList]) +async def show_list(db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["users"])): + return [ + {"id": item.id_, "name": item.name, "lockedOut": item.locked_out, "roles": [p.name for p in sorted(item.roles, key=lambda p: p.name)]} + for item in db.query(User).order_by(User.name).all() + ] - if isinstance(id_, uuid.UUID): - user = self.request.dbsession.query(User).filter(User.id == id_).one() - else: - user = ( - self.request.dbsession.query(User).filter(User.name.ilike(id_)).first() - ) - if self.request.has_permission("Users"): - account = { - "id": user.id, - "name": user.name, - "password": "", - "lockedOut": user.locked_out, - "groups": [], - } - for item in self.request.dbsession.query(Group).order_by(Group.name).all(): - account["groups"].append( - { - "id": item.id, - "name": item.name, - "enabled": True if item in user.groups else False, - } - ) - elif self.user.id == user.id: - account = { - "id": user.id, - "name": user.name, - "password": "", - "lockedOut": user.locked_out, - "groups": [], - } - else: - response = Response("User can only update his/her password") - response.status_int = 500 - return response - return account +@router.get("/active") +async def show_active(db: Session = Depends(get_db), user: User = Depends(get_user)): + return [ + {"name": item.name} + for item in db.query(User).filter(User.locked_out == False).order_by(User.name) + ] - def add_groups(self, user, groups): - for group in groups: - id_ = uuid.UUID(group["id"]) - ug = [g for g in user.groups if g.id == id_] - ug = None if len(ug) == 0 else ug[0] - if group["enabled"] and ug is None: - group_object = ( - self.request.dbsession.query(Group).filter(Group.id == id_).one() - ) - user.groups.append(group_object) - elif not group["enabled"] and ug: - user.groups.remove(ug) + +@router.get("/{id_}", response_model=schemas.Role) +def show_id( + id_: uuid.UUID, + db: Session = Depends(get_db), + user: UserToken = Security(get_user, scopes=["users"]), +): + item = db.query(Role).filter(Role.id_ == id_).first() + return user_info(item, db, user) + + +def user_info(item: Optional[User], db: Session, user: User): + if item is None: + return { + "name": "", "lockedOut": False, "roles": [ + {"id": r.id_, "name": r.name, "enabled": False} + for r in db.query(Role).order_by(Role.name).all() + ] + } + else: + return { + "id": item.id_, + "name": item.name, + "password": "", + "lockedOut": item.locked_out, + "roles": [ + { + "id": r.id_, + "name": r.name, + "enabled": True if r in r.roles else False, + } + for r in db.query(Role).order_by(Role.name).all() + ] if "advanced-delete" in user.permissions else [], + } diff --git a/brewman/routers/cost_centre.py b/brewman/routers/cost_centre.py index c8cf5f49..0d0e488b 100644 --- a/brewman/routers/cost_centre.py +++ b/brewman/routers/cost_centre.py @@ -6,8 +6,9 @@ from fastapi import APIRouter, HTTPException, status, Depends, Security from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm import Session +from ..schemas.auth import UserToken import brewman.schemas.master as schemas -from ..core.security import User, get_current_active_user as get_user +from ..core.security import get_current_active_user as get_user from ..db.session import SessionLocal from ..models.master import CostCentre router = APIRouter() @@ -26,7 +27,7 @@ def get_db(): def save( data: schemas.CostCentreIn, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["cost-centres"]), + user: UserToken = Security(get_user, scopes=["cost-centres"]), ): try: item = CostCentre(name=data.name) @@ -52,7 +53,7 @@ def update( id_: uuid.UUID, data: schemas.CostCentreIn, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["cost-centres"]), + user: UserToken = Security(get_user, scopes=["cost-centres"]), ): try: item = db.query(CostCentre).filter(CostCentre.id == id_).first() @@ -82,7 +83,7 @@ def update( def delete( id_: uuid.UUID, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["cost-centres"]), + user: UserToken = Security(get_user, scopes=["cost-centres"]), ): try: item = db.query(CostCentre).filter(CostCentre.id == id_).first() @@ -113,13 +114,13 @@ def delete( @router.get("/") def show_blank( db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["cost-centres"]), + user: UserToken = Security(get_user, scopes=["cost-centres"]), ): return cost_centre_info(None, db) @router.get("/list", response_model=List[schemas.CostCentre]) -async def show_list(db: Session = Depends(get_db), user: User = Depends(get_user)): +async def show_list(db: Session = Depends(get_db), user: UserToken = Depends(get_user)): return [ {"id": item.id, "name": item.name, "isFixture": item.is_fixture} for item in db.query(CostCentre).order_by(CostCentre.name).all() @@ -130,7 +131,7 @@ async def show_list(db: Session = Depends(get_db), user: User = Depends(get_user def show_id( id_: uuid.UUID, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["cost-centres"]), + user: UserToken = Security(get_user, scopes=["cost-centres"]), ): item = db.query(CostCentre).filter(CostCentre.id == id_).first() return cost_centre_info(item, db) diff --git a/brewman/routers/employee.py b/brewman/routers/employee.py index c093deb4..84b3ccea 100644 --- a/brewman/routers/employee.py +++ b/brewman/routers/employee.py @@ -6,7 +6,8 @@ from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm import joinedload_all, Session from fastapi import APIRouter, HTTPException, status, Depends, Security -from ..core.security import User, get_current_active_user as get_user +from ..schemas.auth import UserToken +from ..core.security import get_current_active_user as get_user from ..db.session import SessionLocal from brewman.models.master import CostCentre, Employee, AccountBase, Account from brewman.models.validation_exception import ValidationError @@ -30,7 +31,7 @@ def get_db(): def save( data: schemas.EmployeeIn, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["employees"]), + user: UserToken = Security(get_user, scopes=["employees"]), ): try: item = Employee( @@ -64,7 +65,7 @@ def update( id_: uuid.UUID, data: schemas.EmployeeIn, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["employees"]), + user: UserToken = Security(get_user, scopes=["employees"]), ): try: item: Employee = db.query(Employee).filter(Employee.id == id_).first() @@ -101,10 +102,10 @@ def update( def delete( id_: uuid.UUID, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["employees"]), + user: UserToken = Security(get_user, scopes=["employees"]), ): employee: Employee = db.query(Employee).filter(Employee.id == id_).first() - can_delete, reason = employee.can_delete("Advanced Delete" in user.permissions) + can_delete, reason = employee.can_delete("advanced-delete" in user.permissions) if can_delete: delete_with_data(employee, db) db.commit() @@ -119,13 +120,13 @@ def delete( @router.get("/") def show_blank( - db: Session = Depends(get_db), user: User = Security(get_user, scopes=["employees"]) + db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["employees"]) ): return employee_info(None, db) @router.get("/list") -async def show_list(db: Session = Depends(get_db), user: User = Depends(get_user)): +async def show_list(db: Session = Depends(get_db), user: UserToken = Depends(get_user)): return [ { "id": item.id, @@ -156,7 +157,7 @@ async def show_term( q: str, c: int = None, db: Session = Depends(get_db), - current_user: User = Depends(get_user), + current_user: UserToken = Depends(get_user), ): list_ = [] for index, item in enumerate(AccountBase.list(10, q, dbsession=db)): @@ -180,7 +181,7 @@ async def show_term( def show_id( id_: uuid.UUID, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["employees"]), + user: UserToken = Security(get_user, scopes=["employees"]), ): return employee_info(id_, db) diff --git a/brewman/routers/product.py b/brewman/routers/product.py index 64dc6f2b..a2e5f8c0 100644 --- a/brewman/routers/product.py +++ b/brewman/routers/product.py @@ -7,8 +7,9 @@ from sqlalchemy import desc from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm import joinedload_all, Session +from ..schemas.auth import UserToken import brewman.schemas.master as schemas -from ..core.security import User, get_current_active_user as get_user +from ..core.security import get_current_active_user as get_user from ..db.session import SessionLocal from ..models.master import Product, Account from ..models.voucher import Voucher, Batch, Inventory, VoucherType @@ -29,7 +30,7 @@ def get_db(): def save( data: schemas.ProductIn, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["products"]), + user: UserToken = Security(get_user, scopes=["products"]), ): try: item = Product( @@ -67,7 +68,7 @@ def update( id_: uuid.UUID, data: schemas.ProductIn, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["products"]), + user: UserToken = Security(get_user, scopes=["products"]), ): try: item: Product = db.query(Product).filter(Product.id == id_).first() @@ -107,10 +108,10 @@ def update( def delete( id_: uuid.UUID, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["products"]), + user: UserToken = Security(get_user, scopes=["products"]), ): product: Product = db.query(Product).filter(Product.id == id_).first() - can_delete, reason = product.can_delete("Advanced Delete" in user.permissions) + can_delete, reason = product.can_delete("advanced-delete" in user.permissions) if can_delete: delete_with_data(product, db) @@ -126,13 +127,13 @@ def delete( @router.get("/") # "Products" def show_blank( - db: Session = Depends(get_db), user: User = Security(get_user, scopes=["products"]) + db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["products"]) ): return product_info(None, db) @router.get("/list") -def show_list(db: Session = Depends(get_db), user: User = Depends(get_user)): +def show_list(db: Session = Depends(get_db), user: UserToken = Depends(get_user)): return [ { "id": item.id, @@ -162,7 +163,7 @@ async def show_term( p: bool = None, e: bool = False, db: Session = Depends(get_db), - current_user: User = Depends(get_user), + current_user: UserToken = Depends(get_user), ): count = c extended = e @@ -192,7 +193,7 @@ async def show_term( def show_id( id_: uuid.UUID, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["accounts"]), + user: UserToken = Security(get_user, scopes=["accounts"]), ): return product_info(id_, db) diff --git a/brewman/routers/product_group.py b/brewman/routers/product_group.py index 5adc4f71..1d3b5a8a 100644 --- a/brewman/routers/product_group.py +++ b/brewman/routers/product_group.py @@ -7,7 +7,8 @@ from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm import Session import brewman.schemas.master as schemas -from ..core.security import User, get_current_active_user as get_user +from ..schemas.auth import UserToken +from ..core.security import get_current_active_user as get_user from ..db.session import SessionLocal from brewman.models.master import ProductGroup router = APIRouter() @@ -26,7 +27,7 @@ def get_db(): def save( data: schemas.ProductGroupIn, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["product-groups"]), + user: UserToken = Security(get_user, scopes=["product-groups"]), ): try: item = ProductGroup(name=data.name) @@ -52,7 +53,7 @@ def update( id_: uuid.UUID, data: schemas.ProductGroupIn, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["product-groups"]), + user: UserToken = Security(get_user, scopes=["product-groups"]), ): try: item = db.query(ProductGroup).filter(ProductGroup.id == id_).first() @@ -82,7 +83,7 @@ def update( def delete( id_: uuid.UUID, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["product-groups"]), + user: UserToken = Security(get_user, scopes=["product-groups"]), ): try: item = db.query(ProductGroup).filter(ProductGroup.id == id_).first() @@ -113,13 +114,13 @@ def delete( @router.get("/") def show_blank( db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["product-groups"]), + user: UserToken = Security(get_user, scopes=["product-groups"]), ): return product_group_info(None, db) @router.get("/list", response_model=List[schemas.ProductGroup]) -async def show_list(db: Session = Depends(get_db), user: User = Depends(get_user)): +async def show_list(db: Session = Depends(get_db), user: UserToken = Depends(get_user)): return[ {"id": item.id, "name": item.name, "isFixture": item.is_fixture} for item in db.query(ProductGroup).order_by(ProductGroup.name).all() @@ -130,7 +131,7 @@ async def show_list(db: Session = Depends(get_db), user: User = Depends(get_user def show_id( id_: uuid.UUID, db: Session = Depends(get_db), - user: User = Security(get_user, scopes=["product-groups"]), + user: UserToken = Security(get_user, scopes=["product-groups"]), ): item = db.query(ProductGroup).filter(ProductGroup.id == id_).first() return product_group_info(item, db) diff --git a/brewman/schemas/auth.py b/brewman/schemas/auth.py index a8189ab3..b9a1698e 100644 --- a/brewman/schemas/auth.py +++ b/brewman/schemas/auth.py @@ -1,8 +1,14 @@ import uuid +from typing import List from datetime import datetime from pydantic import BaseModel +def to_camel(string: str) -> str: + first, *others = string.split('_') + return ''.join([first] + [word.capitalize() for word in others]) + + class Client(BaseModel): id_: uuid.UUID code: int @@ -12,25 +18,88 @@ class Client(BaseModel): creation_date: datetime -class User(BaseModel): - id_: uuid.UUID - name: str - password: str - locked_out: bool - - class LoginHistory(BaseModel): id_: uuid.UUID user_id: uuid.UUID client_id: uuid.UUID date: datetime + class Config: + fields = {'id_': 'id'} + anystr_strip_whitespace = True + alias_generator = to_camel -class Group(BaseModel): + +class PermissionItem(BaseModel): id_: uuid.UUID name: str + enabled: bool + + class Config: + fields = {'id_': 'id'} -class Role(BaseModel): +class RoleIn(BaseModel): + name: str + permissions: List[PermissionItem] + + class Config: + fields = {'id_': 'id'} + anystr_strip_whitespace = True + + +class Role(RoleIn): + id_: uuid.UUID + + +class RoleList(BaseModel): id_: uuid.UUID name: str + permissions: List[str] + + class Config: + fields = {'id_': 'id'} + anystr_strip_whitespace = True + + +class RoleItem(BaseModel): + id_: uuid.UUID + name: str + enabled: bool + + class Config: + fields = {'id_': 'id'} + + +class UserIn(BaseModel): + name: str + password: str + locked_out: bool + roles: List[RoleItem] + + class Config: + fields = {'id_': 'id'} + anystr_strip_whitespace = True + alias_generator = to_camel + + +class User(UserIn): + id_: uuid.UUID + + +class UserList(BaseModel): + id_: uuid.UUID + name: str + roles: List[str] + + class Config: + fields = {'id_': 'id'} + anystr_strip_whitespace = True + + +class UserToken(BaseModel): + id_: uuid.UUID + name: str + locked_out: bool = None + password: str + permissions: List[str] diff --git a/brewman/subscribers.py b/brewman/subscribers.py deleted file mode 100644 index 09494202..00000000 --- a/brewman/subscribers.py +++ /dev/null @@ -1,17 +0,0 @@ -from pyramid.events import subscriber, NewRequest -from pyramid.httpexceptions import HTTPServiceUnavailable -from brewman.models.master import DbSetting - - -@subscriber(NewRequest) -def maintenance_mode(event): - maintenance = ( - event.request.dbsession.query(DbSetting) - .filter(DbSetting.name == "Maintenance") - .first() - ) - if ( - maintenance is not None - and maintenance.data != event.request.authenticated_userid - ): - raise HTTPServiceUnavailable diff --git a/requirements.txt b/requirements.txt index e6b62afb..7fc83cdd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +wheel uvicorn fastapi environs @@ -5,4 +6,5 @@ python-jose[cryptography] passlib[bcrypt] psycopg2 python-multipart -pyjwt \ No newline at end of file +pyjwt +alembic