From be8b011c9c4c44f8de99d5cf19ebd1dae5b7dfe9 Mon Sep 17 00:00:00 2001 From: Blaise Thompson Date: Tue, 12 Nov 2019 08:32:41 -0600 Subject: coloring --- .gitignore | 1 + setup.py | 3 +- shopdb/__init__.py | 10 ++++ shopdb/__main__.py | 123 ++++++++++++++++++++++++++++++++++++++++++++++++ shopdb/_associations.py | 24 ++++++++++ shopdb/_base.py | 16 +++++-- shopdb/_customer.py | 16 +++++++ shopdb/_group.py | 15 ++++++ shopdb/_job.py | 25 ++++++++++ shopdb/_staff.py | 14 ++++++ shopdb/_status.py | 30 ++++++++++++ 11 files changed, 273 insertions(+), 4 deletions(-) create mode 100644 shopdb/__main__.py create mode 100644 shopdb/_associations.py create mode 100644 shopdb/_customer.py create mode 100644 shopdb/_group.py create mode 100644 shopdb/_job.py create mode 100644 shopdb/_staff.py create mode 100644 shopdb/_status.py diff --git a/.gitignore b/.gitignore index bc58411..1222794 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ temp/ flycheck_*.el .projectile *.#* +*#*# # images *.jpg diff --git a/setup.py b/setup.py index 5f0c0c0..111d9c0 100644 --- a/setup.py +++ b/setup.py @@ -21,9 +21,10 @@ setup( packages=find_packages(), package_data=extra_files, python_requires=">=3.7", - install_requires=[], + install_requires=["appdirs", "prettytable"], extras_require={"dev": ["black", "pre-commit", "pydocstyle"]}, version=version, author="Blaise Thompson", author_email="bthompson@chem.wisc.edu", + entry_points={"console_scripts": ["shopdb=shopdb.__main__:main"]}, ) diff --git a/shopdb/__init__.py b/shopdb/__init__.py index d2be0a7..bf39e5c 100644 --- a/shopdb/__init__.py +++ b/shopdb/__init__.py @@ -1 +1,11 @@ from ._base import * +from ._customer import * +from ._job import * +from ._staff import * +from ._status import * + +Base.metadata.create_all(engine) + +from ._associations import * + +Base.metadata.create_all(engine) diff --git a/shopdb/__main__.py b/shopdb/__main__.py new file mode 100644 index 0000000..059aad2 --- /dev/null +++ b/shopdb/__main__.py @@ -0,0 +1,123 @@ +from datetime import datetime +import click +import prettytable +from ._base import Session +from ._customer import Customer +from ._group import Group +from ._job import Job, JobPriorities +from ._staff import Staff +from ._status import Status, StatusValues + + +session = Session() + + +@click.group() +def main(): + pass + + +@main.command(name="customer") +@click.option("--add", is_flag=True, default=False) +def customer(add): + if add: + click.echo("adding new customer") + name = click.prompt("name") + email = click.prompt("email") + room = click.prompt("room") + groups = click.prompt("group id(s)").split(',') + groups = [session.query(Group).filter(Group.id == int(g))[0] for g in groups] + new = Customer(name=name, email=email, room=room, groups=groups) + session.add(new) + session.commit() + click.echo("...done!") + else: + out = prettytable.PrettyTable() + out.field_names = ["id", "name", "email", "room", "group(s)"] + out.align = "l" + for instance in session.query(Customer).order_by(Customer.id): + groups = ",".join([g.name for g in instance.groups]) + out.add_row([instance.id, instance.name, instance.email, instance.room, groups]) + print(out) + + +@main.command(name="group") +@click.option("--add", is_flag=True, default=False) +def group(add): + if add: + click.echo("adding new group") + name = click.prompt("name") + new = Group(name=name) + session.add(new) + session.commit() + click.echo("...done!") + else: + out = prettytable.PrettyTable() + out.field_names = ["id", "name"] + out.align = "l" + for instance in session.query(Group).order_by(Group.id): + out.add_row([instance.id, instance.name]) + print(out) + + +@main.command(name="job") +@click.option("--add", is_flag=True, default=False) +def job(add): + if add: + click.echo("adding new job") + name = click.prompt("name") + customers = click.prompt("customer id(s)").split(',') + customers = [session.query(Customer).filter(Customer.id == int(g))[0] for g in customers] + priority = click.prompt("priority", type=click.Choice([a.name for a in (JobPriorities)])) + new = Job(name=name, customers=customers, priority=priority) + session.add(new) + session.commit() + click.echo("...done!") + else: + out = prettytable.PrettyTable() + out.field_names = ["id", "priority", "name", "customer(s)"] + out.align = "l" + for instance in session.query(Job).order_by(Job.id): + customers = ",".join([c.name for c in instance.customers]) + out.add_row([instance.id, instance.priority.name, instance.name, customers]) + print(out) + + +@main.command(name="staff") +@click.option("--add", is_flag=True, default=False) +def staff(add): + if add: + click.echo("adding new staff member") + name = click.prompt("name") + new = Staff(name=name) + session.add(new) + session.commit() + click.echo("...done!") + else: + out = prettytable.PrettyTable() + out.field_names = ["id", "name"] + out.align = "l" + for instance in session.query(Staff).order_by(Staff.id): + out.add_row([instance.id, instance.name]) + print(out) + + +@main.command(name="status") +@click.option("--add", is_flag=True, default=False) +def staff(add): + if add: + click.echo("recording status change") + job = session.query(Job).filter(Job.id == click.prompt("job id", int))[0] + value = click.prompt("new status", type=click.Choice([a.name for a in (StatusValues)])) + comment = click.prompt("comment") + new = Status(job=job, comment=comment, value=str(value), timestamp=datetime.utcnow()) + session.add(new) + session.commit() + click.echo("...done!") + else: + out = prettytable.PrettyTable() + out.field_names = ["id", "timestamp (UTC)", "job", "value", "comment"] + out.align = "l" + for instance in session.query(Status).order_by(Status.id): + out.add_row([instance.id,instance.timestamp, instance.job.name, instance.value.name, instance.comment]) + print(out) diff --git a/shopdb/_associations.py b/shopdb/_associations.py new file mode 100644 index 0000000..e0e25bf --- /dev/null +++ b/shopdb/_associations.py @@ -0,0 +1,24 @@ +from sqlalchemy import Column, Integer, String, Table +from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from ._base import Base +from ._customer import Customer +from ._group import Group +from ._job import Job + + +customer_group = Table('customer_group', Base.metadata, + Column('customer_id', Integer, ForeignKey('customers.id')), + Column('group_id', Integer, ForeignKey('groups.id')) +) +Customer.groups = relationship("Group", secondary=customer_group, back_populates="members") +Group.members = relationship("Customer", secondary=customer_group, back_populates="groups") + + + +customer_job = Table('customer_job', Base.metadata, + Column('customer_id', Integer, ForeignKey('customers.id')), + Column('job_id', Integer, ForeignKey('jobs.id')) +) +Customer.jobs = relationship("Job", secondary=customer_job, back_populates="customers") +Job.customers = relationship("Customer", secondary=customer_job, back_populates="jobs") diff --git a/shopdb/_base.py b/shopdb/_base.py index 8033d28..5e8c3bc 100644 --- a/shopdb/_base.py +++ b/shopdb/_base.py @@ -1,8 +1,18 @@ -__all__ = ["engine", "Base"] +__all__ = ["engine", "Base", "Session"] +import appdirs +import pathlib import sqlalchemy +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker -engine = sqlalchemy.create_engine("sqlite:///:memory:", echo=True) -Base = sqlalchemy.ext.declarative.declarative_base + +path = pathlib.Path(appdirs.user_data_dir(appname="shopdb")) / "sqlite3.db" +path.parent.mkdir(parents=True, exist_ok=True) +engine = sqlalchemy.create_engine(f"sqlite:///{path}", echo=False) + +Base = declarative_base() + +Session = sessionmaker(bind=engine) diff --git a/shopdb/_customer.py b/shopdb/_customer.py new file mode 100644 index 0000000..05447b5 --- /dev/null +++ b/shopdb/_customer.py @@ -0,0 +1,16 @@ +__all__ = ["Customer"] + + +from sqlalchemy import Column, Integer, String, Table +from ._base import Base, engine + + +class Customer(Base): + __tablename__ = 'customers' + id = Column(Integer, primary_key=True) + name = Column(String) + email = Column(String) + room = Column(String) + + def __repr__(self): + return "" % (self.name) diff --git a/shopdb/_group.py b/shopdb/_group.py new file mode 100644 index 0000000..f79d446 --- /dev/null +++ b/shopdb/_group.py @@ -0,0 +1,15 @@ +__all__ = ["Group"] + + +from sqlalchemy import Column, Integer, String +from sqlalchemy.orm import relationship +from ._base import Base, engine + + +class Group(Base): + __tablename__ = 'groups' + id = Column(Integer, primary_key=True) + name = Column(String) + + def __repr__(self): + return "" % (self.name) diff --git a/shopdb/_job.py b/shopdb/_job.py new file mode 100644 index 0000000..13f2988 --- /dev/null +++ b/shopdb/_job.py @@ -0,0 +1,25 @@ +__all__ = ["Job"] + + +import enum +from sqlalchemy import Column, Integer, String, Enum +from sqlalchemy.orm import relationship +from ._base import Base, engine +from ._status import Status + + +class JobPriorities(enum.Enum): + high = 1 + medium = 2 + low = 3 + + +class Job(Base): + __tablename__ = 'jobs' + id = Column(Integer, primary_key=True) + name = Column(String) + priority = Column(Enum(JobPriorities), default="medium") + status_updates = relationship("Status", back_populates="job") + + def __repr__(self): + return "" % (self.name) diff --git a/shopdb/_staff.py b/shopdb/_staff.py new file mode 100644 index 0000000..27e1944 --- /dev/null +++ b/shopdb/_staff.py @@ -0,0 +1,14 @@ +__all__ = ["Staff"] + + +from sqlalchemy import Column, Integer, String +from ._base import Base, engine + + +class Staff(Base): + __tablename__ = 'staff' + id = Column(Integer, primary_key=True) + name = Column(String) + + def __repr__(self): + return "" % (self.name) diff --git a/shopdb/_status.py b/shopdb/_status.py new file mode 100644 index 0000000..4011048 --- /dev/null +++ b/shopdb/_status.py @@ -0,0 +1,30 @@ +__all__ = ["Status"] + + +import enum +from sqlalchemy import Column, Integer, String, DateTime, Enum +from sqlalchemy.orm import relationship +from sqlalchemy import ForeignKey +from ._base import Base, engine + + +class StatusValues(enum.Enum): + unstarted = 1 + proceeding = 2 + completed = 3 + deferred = 4 + waiting = 5 + canceled = 6 + + +class Status(Base): + __tablename__ = 'event' + id = Column(Integer, primary_key=True) + comment = Column(String) + value = Column(Enum(StatusValues)) + timestamp = Column(DateTime) + job_id = Column(Integer, ForeignKey("jobs.id")) + job = relationship("Job", back_populates="status_updates") + + def __repr__(self): + return "" % (self.value) -- cgit v1.2.3