diff --git a/lib/debug.py b/lib/debug.py index 4f922eb69..8490d6f56 100644 --- a/lib/debug.py +++ b/lib/debug.py @@ -1,9 +1,39 @@ #!/usr/bin/env python3 - from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker -from models import Company, Dev +from models import Company, Dev, Freebie, Base if __name__ == '__main__': engine = create_engine('sqlite:///freebies.db') - import ipdb; ipdb.set_trace() + Base.metadata.create_all(engine) + Session = sessionmaker(bind=engine) + session = Session() + + # querying data from my db (seed data) + first_company = session.query(Company).first() + first_dev = session.query(Dev).first() + first_freebie = session.query(Freebie).first() + + print("Testing print_details() on first freebie:") + if first_freebie: + print(first_freebie.print_details()) + + print("\nTesting oldest_company():") + oldest = Company.oldest_company(session) + print(oldest) + + print("\nTesting received_one() on first dev with item 'Tshirts':") + if first_dev: + print(first_dev.received_one('Tshirts')) + + # Testing give_away() (transfer first freebie from its current owner to another dev if possible) + second_dev = session.query(Dev).filter(Dev.id != first_dev.id).first() if first_dev else None + if first_dev and second_dev and first_freebie: + print(f"\nBefore give_away: {first_freebie.print_details()}") + success = first_dev.give_away(second_dev, first_freebie) + session.commit() + print("Give away success?", success) + print(f"After give_away: {first_freebie.print_details()}") + + import ipdb; ipdb.set_trace() \ No newline at end of file diff --git a/lib/migrations/env.py b/lib/migrations/env.py index c7aab9656..e9bf9fbd8 100644 --- a/lib/migrations/env.py +++ b/lib/migrations/env.py @@ -5,6 +5,12 @@ from alembic import context +#Fixing path issues +import sys +import os +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) + + # this is the Alembic Config object, which provides # access to the values within the .ini file in use. config = context.config @@ -16,9 +22,15 @@ # add your model's MetaData object here # for 'autogenerate' support + +# Import your models here / should inherit from the same Base initialization +from lib.models import Dev,Company,Freebie +# Import the base class +from lib.models import Base + # from myapp import mymodel # target_metadata = mymodel.Base.metadata -from models import Base +from lib.models import Base target_metadata = Base.metadata # other values from the config, defined by the needs of env.py, @@ -76,4 +88,4 @@ def run_migrations_online() -> None: if context.is_offline_mode(): run_migrations_offline() else: - run_migrations_online() + run_migrations_online() \ No newline at end of file diff --git a/lib/models.py b/lib/models.py index 2681bee5a..475c5fd4b 100644 --- a/lib/models.py +++ b/lib/models.py @@ -1,29 +1,91 @@ -from sqlalchemy import ForeignKey, Column, Integer, String, MetaData -from sqlalchemy.orm import relationship, backref +from sqlalchemy import ForeignKey, Column, Integer, String, MetaData, Table +from sqlalchemy.orm import relationship from sqlalchemy.ext.declarative import declarative_base convention = { "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", } metadata = MetaData(naming_convention=convention) - Base = declarative_base(metadata=metadata) +# Junction table for many-to-many between Company and Dev +company_dev = Table( + 'company_dev', + Base.metadata, + Column('company_id', Integer, ForeignKey('companies.id'), primary_key=True), + Column('dev_id', Integer, ForeignKey('devs.id'), primary_key=True) +) + class Company(Base): __tablename__ = 'companies' - id = Column(Integer(), primary_key=True) - name = Column(String()) - founding_year = Column(Integer()) + id = Column(Integer, primary_key=True) + company_name = Column(String, nullable=False) + founding_year = Column(Integer) + + # Relationships + devs = relationship("Dev", secondary="company_dev", back_populates="companies") + freebies = relationship("Freebie", back_populates="company") + + def give_freebie(self, dev, item_name, value): + """Create a new Freebie for a Dev from this Company.""" + new_freebie = Freebie(item_name=item_name, value=value, company=self, dev=dev) + return new_freebie + + @classmethod + def oldest_company(cls, session): + """Return the Company with the earliest founding year.""" + return session.query(cls).order_by(cls.founding_year.asc()).first() def __repr__(self): - return f'' + return f"" + class Dev(Base): __tablename__ = 'devs' - id = Column(Integer(), primary_key=True) - name= Column(String()) + id = Column(Integer, primary_key=True) + dev_name = Column(String, nullable=False) + + # Relationships + companies = relationship("Company", secondary="company_dev", back_populates="devs") + freebies = relationship("Freebie", back_populates="dev") + + #aggregate methods + def received_one(self, item_name): + """Return True if the Dev has received a freebie with the given item name.""" + return any(freebie.item_name == item_name for freebie in self.freebies) + + def give_away(self, other_dev, freebie): + """ + Transfer ownership of a freebie to another Dev, + only if the current Dev owns it. + """ + if freebie in self.freebies: + freebie.dev = other_dev + return True + return False + + def __repr__(self): + return f"" + +class Freebie(Base): + __tablename__ = 'freebies' + + id = Column(Integer, primary_key=True) + value = Column(Integer, nullable=False) + item_name = Column(String, nullable=False) + company_id = Column(Integer, ForeignKey('companies.id'), nullable=False) + dev_id = Column(Integer, ForeignKey('devs.id'), nullable=False) + + # Relationships + company = relationship("Company", back_populates="freebies") + dev = relationship("Dev", back_populates="freebies") + + def print_details(self): + return f"{self.dev.dev_name} owns a {self.item_name} from {self.company.company_name}" def __repr__(self): - return f'' + dev_name = self.dev.dev_name if self.dev else "Unknown Dev" + company_name = self.company.company_name if self.company else "Unknown Company" + return f"" \ No newline at end of file diff --git a/lib/seed.py b/lib/seed.py index b16becbbb..55c842bab 100644 --- a/lib/seed.py +++ b/lib/seed.py @@ -1,3 +1,64 @@ #!/usr/bin/env python3 -# Script goes here! + +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker +from models import Company, Dev, Freebie + +from faker import Faker + +import random + +# Connect to Database +if __name__ == '__main__': + engine = create_engine('sqlite:///freebies.db') + Session = sessionmaker(bind=engine) + session = Session() + + fake = Faker() # Instantiating it then using it to generate dummy data + + #dev instance + devs = [] + for _ in range(6): + dev = Dev( + dev_name = fake.name() + ) + devs.append(dev) + session.add_all(devs) + session.commit() + + + #company instance + companies = [] + for _ in range (6): # the _ represents a placeholder for a var we dont need + company = Company( + company_name = fake.company(), + founding_year = random.randint(2010,2020) + ) + companies.append(company) + session.add_all(companies) + session.commit() #save + + # My Junction -> Many to Many table (company_dev table) + for dev in devs: + related_companies = random.sample(companies, random.randint(1,5)) + for company in related_companies: + dev.companies.append(company) + session.commit() + + # freebies has-manys + freebies = [] + item_names = ['Flask', 'Tshirts', 'stickers', 'Notebook', 'Pens','Gadgets'] + for _ in range(10): + freebie = Freebie( + item_name=random.choice(item_names), + value=random.randint(1,10), + company=random.choice(companies), + dev=random.choice(devs) + ) + freebies.append(freebie) + session.add_all(freebies) + session.commit() + + print("Congrats Data Seeded,lol ") + \ No newline at end of file