Dev./Python

Python - Mini project : Library Management System 4

Ivan'show 2023. 7. 20.
728x90
반응형

도서 대출 기능

우선 도서를 대출 하는 과정을 상상해 보면, 조회해서 어떤 책들이 있는지 알고 있는 상태이다.

그런데 한권만 대출하나 ? 여러권도 가능할 것이다.

, 로 구분 지어서 입력 받아서 리스트에 저장한뒤에 리스트에서 쭉 for 문을 돌려서 실행 시키도록 해보자

# 입력 받는 부분 테스트 해보기
def lend_book():
    connection = psycopg2.connect(host=DATABASE_HOST, user=DATABASE_USER, password=DATABASE_PASSWORD,
                                  dbname=DATABASE_NAME, port=DATABASE_PORT)
    cursor = connection.cursor()

    input_ids = input("대출할 책의 id 들을 (,)로 구분하여 입력해주세요 :")
    print(input_ids.split(","))

# 대출할 책의 id 들을 (,)로 구분하여 입력해주세요 :1,2,4,15,2,24,3,4
# ['1', '2', '4', '15', '2', '24', '3', '4']

공백을 처리해야할 필요성이 생김, 하지만 책 이름에도 공백이 있을 수 있다는 것을 명심

[python] 파이썬 공백 제거 (replace, strip) 2가지 방법

lend_book() 기능

def lend_book():
    connection = psycopg2.connect(host=DATABASE_HOST, user=DATABASE_USER, password=DATABASE_PASSWORD,
                                  dbname=DATABASE_NAME, port=DATABASE_PORT)
    cursor = connection.cursor()

    # input_ids = input("대출할 책의 id 들을 (,)로 구분하여 입력해주세요 :")
    # print(input_ids.split(","))
    # book_ids = []

    while True:
        lend_option = lend_book_option()
        # 도서 ID를 입력받아 해당 글자가 들어간 제목을 가진 도서 모두 조회
        if lend_option == 1:
            book_ids = []  # 최종 작업할 리스트
            try:
                input_ids = input("대출할 책의 정확한 ID를 (,)로 구분하여 입력해주세요 :")
                split_input = input_ids.split(",")  # ,로 구분 짓기
                for id in split_input:  # 돌면서
                    if id.strip() != "":  # 공백만 있는거 제거
                        book_ids.append(int(id.strip()))  # 제목에 양쪽 끝 공백 제거 후 담기
            except ValueError:
                print("\\n값을 잘못 입력했습니다.\\n")
                continue

            print(book_ids)
            # 담긴 제목으로 전부 SQL 작업 시작
            for input_book_id in book_ids:
                # 우선 해당 제목의 책이 있는지 조회
                cursor.execute("""SELECT * FROM books WHERE book_id = %s;""", (input_book_id,))
                row = cursor.fetchone()

                if row == None:  # 혹시 입력한 정보로 찾을 수 없을 경우 돌아가게끔 처리
                    print("\\n")
                    print("\\n")
                    print(f"\\n해당 ID({input_book_id})를 가진 도서는 찾을 수 없습니다.")
                    print("다시 검색해 주세요.\\n")
                    continue

                # 해당 책의 is_available 이 True 면
                if row[4]:
                    loan_date = date.today()
                    try:
                        # loans 테이블에 삽입
                        cursor.execute("""INSERT INTO loans (book_id, loan_date) VALUES (%s, %s);""",
                                       (input_book_id, loan_date,))
                        # books 테이블에 is_available 을 FALSE 로 변경
                        cursor.execute("""UPDATE books SET is_available = FALSE WHERE book_id = %s;""",
                                       (input_book_id,))
                        print(f"{row[1]}, 대출 성공")
                        connection.commit()
                    except: # 양쪽에 작업을 해야하니 에러 발생시 돌리기
                        connection.rollback()
                else:
                    print(f"\\n책 번호 : {row[0]}, 책 제목 :{row[1]}, 현재 대출 가능한 도서가 아닙니다.\\n")

            next_action = str(input("다음 작업이 있습니까? [Y/N] :"))
            if next_action.upper() == "Y":
                lend_book()  # 재귀
            elif next_action.upper() == "N":
                # 다음 작업이 없이 프로그램이 종료될테니 데이터베이스와 연결 종료
                print("DB close executed")
                cursor.close()
                connection.close()
                print("DB close done")
                raise ExitProgram
            else:
                print("\\n")
                print("잘못 입력하셨습니다. 도서 검색 옵션으로 되돌아 갑니다.")
                print("\\n")

        # 대출 중인 모든 목록 조회
        elif lend_option == 2:
            cursor.execute("""
                SELECT * FROM books WHERE is_available = FALSE ORDER BY book_id;
                """)
            rows = cursor.fetchall()

            print("\\n현재 모든 도서 정보:")
            print("------------------------------------------------------------------")
            print("    ID    |   title   |    Author   |  Publisher  | Availability |")
            print("------------------------------------------------------------------")

            for row in rows:  # 아직 꾸미지 않은 상태
                print(row)
            print("\\n")

            next_action = str(input("다음 작업이 있습니까? [Y/N] :"))
            if next_action.upper() == "Y":
                lend_book()
            elif next_action.upper() == "N":
                # 다음 작업이 없이 프로그램이 종료될테니 데이터베이스와 연결 종료
                print("DB close executed")
                cursor.close()
                connection.close()
                print("DB close done")
                raise ExitProgram

        elif lend_option == 0:
            print("\\n")
            print("이전 페이지로 돌아갑니다.")
            print("\\n")
            # 다음 작업이 없이 메인으로 돌아가니 데이터베이스와 연결 종료
            print("DB close executed")
            cursor.close()
            connection.close()
            print("DB close done")
            raise ReturnToMainMenu

 

 

도서 반납 기능

도서 받납의 순서는 유저가 도서를 가져오면 해당정보(book_id) 를 입력받아서 books 와 loans 에 값을 업데이트 하면 끝이다.

def return_book():
    connection = psycopg2.connect(host=DATABASE_HOST, user=DATABASE_USER, password=DATABASE_PASSWORD,
                                  dbname=DATABASE_NAME, port=DATABASE_PORT)
    cursor = connection.cursor()

    print("도서를 반납합니다.\\n")
    try:
        book_ids = []
        return_book_id = input("가져온 도서의 ID를 (,)로 구분하여 입력해주세요 :")

        split_input = return_book_id.split(",")  # ,로 구분 짓기
        for id in split_input:  # 돌면서
            if id.strip() != "":  # 공백만 있는거 제거
                book_ids.append(int(id.strip()))  # 제목에 양쪽 끝 공백 제거 후 담기

        for return_id in book_ids:
            cursor.execute("""SELECT * FROM books WHERE book_id = %s AND is_available = FALSE;""", (return_id,))
            row = cursor.fetchone()

            if row == None:  # 혹시 입력한 정보로 찾을 수 없을 경우 돌아가게끔 처리
                print(f"\\n해당 ID({return_id})를 가진 도서는 반납예정 데이터에 없습니다.")
                print("다시 검색해 주세요.\\n")
                continue

            if row[0]:
                return_date = date.today()
                try:
                    # is_available 다시 True 로 돌려놓기
                    cursor.execute("""UPDATE books SET is_available = TRUE WHERE book_id = %s;""", (return_id,))
                    # loans 에 return_date 추가하기
                    cursor.execute("""UPDATE loans SET return_date = %s WHERE book_id = %s;""",
                                   (return_date, return_id,))
                    connection.commit()
                    print(f"{row[1]}, 반납 성공")
                except:
                    connection.rollback()
                    print("DB close executed")
                    cursor.close()
                    connection.close()
                    print("DB close done")
                    return
            else:
               print(f"\\n책 번호 : {row[0]}, 책 제목 :{row[1]}, 현재 반납 가능한 도서가 아닙니다.\\n")
    except ValueError:
        print("\\n잘못된 정보를 입력하셨습니다.")
        print("DB close executed")
        cursor.close()
        connection.close()
        print("DB close done")
        return

 

 

 

대출중인 도서를 모두 조회하는 기능

기존에 있던 대출 도서 조회 기능에 LEFT 조인으로 값을 가져오는 형태로 구현해보았다.

# 대출 중인 모든 목록 조회
        elif lend_option == 2:
            cursor.execute("""SELECT b.*, l.loan_id, l.loan_date, l.return_date FROM books AS b LEFT JOIN loans AS l ON b.book_id = l.book_id WHERE b.is_available = FALSE AND l.return_date IS NULL;""")
            rows = cursor.fetchall()

            print("\\n현재 대출중인 모든 도서 정보입니다.")
            print(
                "------------------------------------------------------------------------------------------------------------")
            print(
                "|  Book ID  |   title   |    Author   |  Publisher  | Availability |  LoanID  | Taken Date |  Return Date  |")
            print(
                "------------------------------------------------------------------------------------------------------------")

            if len(rows) == 0:
                print("\\n현재 대출중인 도서가 없습니다.\\n")
            else:
                for row in rows:  # 아직 꾸미지 않은 상태
                    print(row)
                print("\\n")

            next_action = str(input("다음 작업이 있습니까? [Y/N] :"))
            if next_action.upper() == "Y":
                lend_book()
            elif next_action.upper() == "N":
                # 다음 작업이 없이 프로그램이 종료될테니 데이터베이스와 연결 종료
                print("DB close executed")
                cursor.close()
                connection.close()
                print("DB close done")
                raise ExitProgram

 

 

도서 입력 기능에 CSV 파일로 입력할 수 있게 만들기

pyhton 에서 제공하는 라이브러리인 csv, tkinter 를 이용하여 파일 선택 팝업창을 띄우고 csv 파일을 읽어와 “,” 로 구분지에 데이터를 삽입시켜주는 과정

import csv
import tkinter
from tkinter import filedialog

# ....

def insert_book():  # 파일로 추가하는 부분은 나중에
    connection = create_connection()
    cursor = create_cursor(connection)

    while True:
        insert_option = insert_book_option()
        if insert_option == 1:
            print("새로운 도서를 추가합니다.\\n")
            title = input("도서 제목을 입력하세요 : ")
            author = input("저자를 입력하세요 : ")
            publisher = str(input("출판사를 입력하세요 : "))
            # query = """INSERT INTO books (title, author, publisher) VALUES (%s, %s, %s);"""
            # values = (title, author, publisher,)
            try:
                cursor.execute("""INSERT INTO books (title, author, publisher) VALUES (%s, %s, %s);""",
                               (title, author, publisher,))
                # cursor.execute(query, values)
                connection.commit()
            except:
                connection.rollback()
                print("\\n에러 발생, 작업을 롤백합니다.\\n")
                disconnect_db(connection, cursor)
                return

        elif insert_option == 2:
            print("새로운 도서를 csv 파일로 추가합니다.\\n")
            root = tkinter.Tk()
            root.withdraw()
            csv_file = filedialog.askopenfilename(filetypes=[("CSV Files", "*.csv")])

            if csv_file:
                try:
                    with open(csv_file,'r', newline='') as file:
                        csv_data = csv.reader(file)
                        next(csv_data)

                        for row in csv_data:
                            if len(row) == 1:
                                data = row[0].split(",")
                                title, author, publisher = data[0].strip(), data[1].strip(), data[2].strip()
                                cursor.execute("""INSERT INTO books (title, author, publisher) VALUES (%s, %s, %s);""",
                                               (title, author, publisher,))
                                connection.commit()
                            else:
                                print(f"\\n데이터 형식 오류, row:{row}")

                except Exception as e:
                    connection.rollback()
                    print(f"에러가 발생하였습니다. message : {str(e)}")
                    disconnect_db(connection, cursor)
                    continue
            else:
                print("\\n파일이 선택되지 않았습니다.")
                disconnect_db(connection, cursor)
                continue

        elif insert_option == 0:
            print("\\n이전 페이지로 돌아갑니다.\\n")
            # 다음 작업이 없이 메인으로 돌아가니 데이터베이스와 연결 종료
            disconnect_db(connection, cursor)
            raise ReturnToMainMenu

        # print("\\n도서가 추가되었습니다.\\n")
        #     disconnect_db(connection, cursor)

 

728x90
반응형

댓글