
13 changed files with 529 additions and 27 deletions
Binary file not shown.
@ -0,0 +1,344 @@
@@ -0,0 +1,344 @@
|
||||
import sys |
||||
import sqlite3 |
||||
import argparse |
||||
from pathlib import Path |
||||
from datetime import datetime |
||||
from urllib.parse import urlparse |
||||
|
||||
from sqlalchemy import func |
||||
from pyramid.paster import bootstrap, setup_logging, get_appsettings |
||||
from sqlalchemy.exc import OperationalError |
||||
from sqlalchemy.orm.exc import NoResultFound |
||||
|
||||
from .. import models, adapters, services |
||||
|
||||
vendor_map = { |
||||
"Accurion GmbH": ["accurion"], |
||||
"Acros Organics": ["acros"], |
||||
"Agilent Technologies": ["agilent"], |
||||
"Alfa Aesar": [ |
||||
"alefa aesar", |
||||
"alfa", |
||||
"aesar", |
||||
"alfa aesar - vwr", |
||||
"alfa-aesar", |
||||
"alfaaesar", |
||||
], |
||||
"Amazon": [], |
||||
"analytics-shop.com": ["analytics-shop"], |
||||
"architekturbedarf.de": ["architekturbedarf"], |
||||
"Avanti Polar Lipids": ["avanti"], |
||||
"Biesterfeld Spezialchemie GmbH": ["biesterfeld", "biesterfeld gmbh"], |
||||
"Bio-Rad": ["bio rad"], |
||||
"Biocat": [], |
||||
"Bioleague GmbH & co.kg": ["bioleague"], |
||||
"Biomol": [], |
||||
"Bürkert Indelfingen": ["bürkert"], |
||||
"Carl Roth GmbH": [ |
||||
"carl roth", |
||||
"carl-roth", |
||||
"carlroth", |
||||
"cr", |
||||
"karl roth", |
||||
"roth", |
||||
], |
||||
"Cellsystems Biotech": ["cellsystems"], |
||||
"Chemicell GmbH": ["chemicell"], |
||||
"Clickbox e.k.": ["clickbox"], |
||||
"Cole Parmer": ["coleparmer"], |
||||
"Conrad Electronics": [ |
||||
"conrad", |
||||
"conrad electronic", |
||||
"conrad, fax 09604408937, k-nr 6043142", |
||||
], |
||||
"Cytoskeleton inc": ["cytoskeleton"], |
||||
"Daniel Maas Dichtstoffhandel & Co.": ["daniel maas"], |
||||
"Delta Mask b.v.": ["delta mask", "deltamask"], |
||||
"der-rollende-shop.de": ["der-rollende-shop"], |
||||
"Dianova": [], |
||||
"Distrelec": ["distrilec"], |
||||
"Edmund Optics GmbH": ["edmund optics", "edmund"], |
||||
"Faust Lab Science GmbH": ["faust", "faust lab"], |
||||
"Fisher Scientific": [ |
||||
"fischer scientific", |
||||
"fisher scientific/acros organic", |
||||
], |
||||
"form.in Lasercenter": ["form.in"], |
||||
"Uwe Markus (Glasbläser)": [ |
||||
"glasbläser markus", |
||||
"markus", |
||||
"markus, glasbläser", |
||||
"uwe markus", |
||||
"glasbläser", |
||||
], |
||||
"Goodfellow": ["good fellow"], |
||||
"Greiner Bio-One": ["greiner bio one"], |
||||
"Hach": [], |
||||
"Hellma GmbH & Co KG": [ |
||||
"hellma analytics", |
||||
"hellma optics", |
||||
"hellma optik jena", |
||||
], |
||||
"Hiss dx": ["hiss"], |
||||
"HJ-Bioanalytik GmbH": ["hj bioanalytik gmbh", "hj bioanalytik"], |
||||
"laborhandel24.de": ["laborhandel24"], |
||||
"locheisen.com": ["locheisen"], |
||||
"praezisionsmesstechnik.de": ["praezisionsmesstechnik"], |
||||
"siebgewebeshop.de": ["siebgewebeshop"], |
||||
"Häberle Labortechnik": ["häberle"], |
||||
"High-Tech-Flon": ["hightechflon"], |
||||
"hygie.de": ["hygie"], |
||||
"Iolitec": [ |
||||
"ionic liquids technologie", |
||||
"ionic liquids technologies", |
||||
"iolitec ionic liquids technologies", |
||||
], |
||||
"Iris Biotech GmbH": ["iris biotech"], |
||||
"Ismatec": ["ismatec/idex"], |
||||
"Jackson Immunoresearch": ["jacksonimmuno", "jackson"], |
||||
"Kinesis Abimed": ["kinesis", "kinesisgmbh"], |
||||
"Kisker Biotech GmbH & co. kg": ["kisker"], |
||||
"Knick Elektronische Messgeräte GmbH": ["knick"], |
||||
"Kummer Laborbedarf": ["kummer"], |
||||
"Laborhandel Krumpholz": ["krumpholz"], |
||||
"leuchtmittelmarkt.com": ["leuchtmittelmarkt"], |
||||
"Life Sciences Advanced Technologies inc": [ |
||||
"life sciences advanced technologies", |
||||
], |
||||
"Life Technologies": ["lifetechnologies", "ife technologies"], |
||||
"Macherey Nagel": ["m-n", "mn", "macherey-nagel"], |
||||
"magnets4you GmbH": ["magnets4you"], |
||||
"magnet-shop.com": ["magnet-shop"], |
||||
"Mercateo ag": ["mercateo"], |
||||
"Merck": ["merck über vwr"], |
||||
"merck berufsbekleidung": [ |
||||
"merck berufskleidung", |
||||
"merck-berufsbekleidung", |
||||
], |
||||
"Merck millipore inc.": ["merck millipore", "merckmillipore"], |
||||
"Mettler-Toledo GmbH": ["mettler toledo", "mettler-toledo", "mettler"], |
||||
"Micro Particles GmbH": ["micro particles"], |
||||
"Microdyn-Nadir GmbH": ["microdyn-nadir"], |
||||
"Millipore GmbH": ["millipore"], |
||||
"Molecular Devices / Genetix": ["molecular devices", "genetix"], |
||||
"Nanoandmore GmbH": ["nano-and-more", "nanoandmore"], |
||||
"Nanocyl s.a.": ["nanocyl"], |
||||
"Neo Lab": ["neolab"], |
||||
"Newport Spectra-Physics": ["newport"], |
||||
"OCO Ortenauer Gase GmbH": ["oco ortenauer gase", "oco"], |
||||
"Pall Corporation": ["pall"], |
||||
"Plano GmbH": ["plano", "plano-eu", "plano-em"], |
||||
"Polyan GmbH": ["polyan"], |
||||
"Polyscience Europa GmbH": [ |
||||
"polysciences", |
||||
"polysciences europe gmbh", |
||||
"polysciences, inc.", |
||||
], |
||||
"ProLiquid GmbH": ["pro-liquid"], |
||||
"Qiagen": ["quiagen"], |
||||
"R&D Systems": ["r&d system"], |
||||
"Reichelt Elektronik": ["reichelt"], |
||||
"RS Components": ["rs"], |
||||
"S-Polytec": ["s-polytech"], |
||||
"Sarstedt AG & Co. KG": ["sarstedt"], |
||||
"Science Services GmbH": ["science services"], |
||||
"Scienion AG": ["scienion"], |
||||
"Sigma Aldrich": [ |
||||
"aldrich", |
||||
"adrich", |
||||
"aldich", |
||||
"aldritch", |
||||
"aldrích", |
||||
"fluka", |
||||
"sa", |
||||
"sigma - aldrich", |
||||
"sigma adrich", |
||||
"sigma aldich", |
||||
"sigma aldritch", |
||||
"sigma aldrích", |
||||
"sigma- aldrich", |
||||
"sigma-adrich", |
||||
"sigma-aldrich", |
||||
"sigma-aldrich (fluka)", |
||||
"sigmaaldrich", |
||||
"roche, sigma-aldrich", |
||||
"sigmar", |
||||
"sigma", |
||||
], |
||||
"Sterlitech": [], |
||||
"Supermagnete": ["supermagnet"], |
||||
"taq-dna.com": ["taq-dna"], |
||||
"TCI Deutschland GmbH": [ |
||||
"tci", |
||||
"tci chemical", |
||||
"tci chemicals", |
||||
"tci deutschland", |
||||
"tci europe", |
||||
"tci europe n.v.", |
||||
], |
||||
"Thermo Fisher Scientific": [ |
||||
"themofisher", |
||||
"thermofischer", |
||||
"thermofisher", |
||||
"thermo fisher", |
||||
"thermofisher scientific", |
||||
"thermo scientific", |
||||
"thermo scientific - www.perbio.com", |
||||
"perbio", |
||||
"thermo scientific / pierce", |
||||
"thermo ", |
||||
"pierce", |
||||
], |
||||
"Tib MolBiol": ["tibmolbiol", "tibmolbio"], |
||||
"Tse Systems GmbH": ["tse systems"], |
||||
"Vilber Lourmat GmbH": ["vilber"], |
||||
"VWR International GmbH": [ |
||||
"vwr", |
||||
"vwr (lenz laborglas gmbh & co.kg)", |
||||
"vwr chemicals", |
||||
"vwr collection", |
||||
"vwt", |
||||
], |
||||
"Weigert": ["drweigert"], |
||||
"Xantec Bioanalytics": ["xantec", "xantec bioanalyticss"], |
||||
"Zitt-Thoma": ["zitt thoma"], |
||||
} |
||||
|
||||
|
||||
def _query_table(cursor, table): |
||||
cursor.execute(f"SELECT * FROM {table}") |
||||
columns = [d[0] for d in cursor.description] |
||||
return (dict(zip(columns, values)) for values in cursor) |
||||
|
||||
|
||||
def _case_insensitive_query_user_by_username(repo, reference): |
||||
try: |
||||
user = ( |
||||
repo.session.query(models.User) |
||||
.filter(func.lower(models.User.username) == func.lower(reference)) |
||||
.one() |
||||
) |
||||
return user.username |
||||
except NoResultFound: |
||||
return reference |
||||
|
||||
|
||||
def migrate(old_db, repo): |
||||
inpsql3 = sqlite3.connect(old_db) |
||||
cursor = inpsql3.cursor() |
||||
migrate_users(cursor, repo) |
||||
migrate_vendors(cursor, repo) |
||||
migrate_orders(cursor, repo) |
||||
|
||||
|
||||
def migrate_users(cursor, repo): |
||||
for old_user in _query_table(cursor, "users"): |
||||
user = models.User( |
||||
old_user["id"], |
||||
old_user["user_name"], |
||||
old_user["first_name"], |
||||
old_user["last_name"], |
||||
old_user["email"], |
||||
old_user["password_hash"], |
||||
models.UserRole[old_user["role"]], |
||||
) |
||||
repo.add_user(user) |
||||
|
||||
|
||||
def migrate_vendors(cursor, repo): |
||||
for name, replacements in vendor_map.items(): |
||||
vendor = models.Vendor(name.lower(), name) |
||||
repo._add_item_to_db(vendor) |
||||
for replacement in replacements: |
||||
vendor = models.Vendor(replacement.lower(), name) |
||||
repo._add_item_to_db(vendor) |
||||
|
||||
|
||||
def migrate_orders(cursor, repo): |
||||
status_fields = [ |
||||
("created", models.OrderStatus.OPEN), |
||||
("approval", models.OrderStatus.APPROVAL), |
||||
("ordered", models.OrderStatus.ORDERED), |
||||
("completed", models.OrderStatus.COMPLETED), |
||||
] |
||||
|
||||
for old_order in _query_table(cursor, "orders"): |
||||
|
||||
result = services.check_vendor_name(repo, old_order["vendor"]) |
||||
if result.found: |
||||
vendor = result.name |
||||
else: |
||||
vendor = old_order["vendor"] |
||||
repo._add_item_to_db(models.Vendor(result.name.lower(), vendor)) |
||||
|
||||
order = models.OrderItem( |
||||
old_order["id"], |
||||
old_order["cas_description"], |
||||
old_order["catalog_nr"], |
||||
vendor, |
||||
models.OrderCategory[old_order["category"]], |
||||
old_order["package_size"], |
||||
old_order["unit_price"], |
||||
old_order["amount"], |
||||
old_order["currency"], |
||||
old_order["account"], |
||||
old_order["comment"], |
||||
) |
||||
repo.add_order(order) |
||||
|
||||
for old_field, status in status_fields: |
||||
field_by = old_order[f"{old_field}_by"] |
||||
|
||||
if field_by: |
||||
field_date = datetime.fromisoformat( |
||||
old_order[f"{old_field}_date"] |
||||
) |
||||
user = _case_insensitive_query_user_by_username(repo, field_by) |
||||
log_entry = models.LogEntry( |
||||
order.id, status, user, field_date, |
||||
) |
||||
order.add_to_log(log_entry) |
||||
|
||||
|
||||
def parse_args(argv): |
||||
parser = argparse.ArgumentParser() |
||||
parser.add_argument( |
||||
"config_uri", help="Configuration file, e.g., development.ini", |
||||
) |
||||
parser.add_argument( |
||||
"old_db", help="ordr2 sqlite database file", |
||||
) |
||||
return parser.parse_args(argv[1:]) |
||||
|
||||
|
||||
def main(argv=sys.argv): |
||||
args = parse_args(argv) |
||||
setup_logging(args.config_uri) |
||||
env = bootstrap(args.config_uri) |
||||
settings = get_appsettings(args.config_uri) |
||||
|
||||
# remove an existing sqlite database to issue a restart |
||||
database_url = urlparse(settings["sqlalchemy.url"]) |
||||
dabase_path = Path(database_url.path) |
||||
if database_url.scheme == "sqlite" and dabase_path.is_file(): |
||||
dabase_path.unlink() |
||||
|
||||
try: |
||||
with env["request"].tm: |
||||
repo = env["request"].repo |
||||
adapters.metadata.create_all(repo.session.get_bind()) |
||||
migrate(args.old_db, repo) |
||||
except OperationalError: |
||||
print( |
||||
""" |
||||
Pyramid is having a problem using your SQL database. The problem |
||||
might be caused by one of the following things: |
||||
|
||||
1. You may need to initialize your database tables with `alembic`. |
||||
Check your README.txt for description and try to run it. |
||||
|
||||
2. Your database server may not be running. Check that the |
||||
database server referred to by the "sqlalchemy.url" setting in |
||||
your "development.ini" file is running. |
||||
""" |
||||
) |
Loading…
Reference in new issue