def find_seller_name(**kwargs):
    """ 셀러 리스트 목록 찾는 API
    API 작성:
        최진아

    Header:
        Authorizaion: jwt

    Args:
        seller_name : 셀러 한글 이름

    Returns:
        {data : seller_list}, http status code

    Exceptions:
        InternalError: DATABASE가 존재하지 않을 때 발생
        OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
        ProgramingError: SQL syntax가 잘못되었을 때 발생
        IntegrityError: Key의 무결성을 해쳤을 때 발생
        DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
        KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
    """
    db = None
    try:
        role_id = kwargs['role_id']
        seller_name = request.args['seller_name']

        db = get_db_connector()
        if db is None:
            return jsonify(message="DATABASE_INIT_ERROR"), 500

        # 마스터 권한 전용이므로 셀러인 경우 요청 drop
        if role_id == SELLER_ROLE_ID:
            return jsonify(message="UNAUTHORIZED"), 401
        # 권한 정보가 없는 경우 에러
        if main_dao.role(db, role_id) is None:
            return jsonify(message="DATA_DOES_NOT_EXIST"), 404

        if role_id == MASTER_ROLE_ID:
            seller_data = product_dao.similar_seller_name(db, seller_name)

            seller_list = [{
                    "id": seller['user_id'],
                    "name": seller['seller_name'],
                    "image": seller['profile_image']
                }for seller in seller_data]

            return jsonify(data=seller_list), 200

    except pymysql.err.InternalError:
        return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
    except pymysql.err.OperationalError:
        return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
    except pymysql.err.ProgrammingError:
        return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
    except pymysql.err.IntegrityError:
        return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
    except pymysql.err.DataError:
        return jsonify(message="DATA_ERROR"), 400
    except KeyError:
        return jsonify(message="KEY_ERROR"), 400
    except Exception as e:
        return jsonify(message=f"{e}"), 500
    finally:
        if db:
            db.close()
def product_list(**kwargs):
    """상품관리 리스트 및 필터
        API 작성:
            최진아

        Header:
            Authorizaion: jwt

         Query Strings: 필터링 옵션
            start_period: 조회 시작 기간
            end_period: 조회 마지막 기간
            seller_name: 셀러 한글 이름
            seller_attribute: 셀러 구분
            product_name: 상품명
            product_id: 상품번호
            code: 상품코드
            on_sale : 판매여부
            on_list: 진열여부
            discount: 할인여부
            limit : pagination
            offset : pagination

        Returns:
            {data = product_list}, http status code

        Exceptions:
            InternalError: DATABASE가 존재하지 않을 때 발생
            OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
            ProgramingError: SQL syntax가 잘못되었을 때 발생
            IntegrityError: 컬럼의 무결성을 해쳤을 때 발생
            DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
            KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
            ValidationError : 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
    """

    db = None
    try:
        # filter의 validation 확인
        validate(request.args, PRODUCT_FILTER_SCHEMA)

        role_id = kwargs['role_id']
        user_id = kwargs['user_id']

        # pagination 조건 생성
        filter_dict = {}
        filter_dict['limit'] = request.args.get('limit', 10, int)
        filter_dict['offset'] = request.args.get('offset', 0, int)

        # 권한이 마스터인 경우의  필터 조건 생성
        if role_id == MASTER_ROLE_ID:
            filter_list = ['start_period', 'end_period', 'seller_name', 'user_id', 'product_name', 'product_id', 'code', 'on_sale', 'on_list', 'discount']

            for filter_key in filter_list:
                filter_dict[filter_key] = request.args.get(filter_key, None)

            if filter_dict['end_period']:
                end_date = parse(filter_dict['end_period'])
                add_date = datetime.timedelta(days = 1)
                end_period = end_date + add_date
                filter_dict['end_period'] = end_period

            # seller_attribute_id 값 리스트로 저장 / 잘못된 필터 데이터가 들어오면 에러 return
            seller_attribute_check_list = ['1','2','3','4','5','6','7']
            seller_attributes = tuple(request.args.getlist('seller_attribute', None))
            for seller_attribute in seller_attributes:
                if seller_attribute not in seller_attribute_check_list:
                    return jsonify(message = "DATA_ERROR"), 400
            filter_dict['seller_attribute'] = seller_attributes

            db = get_db_connector()

            #seller_name을 user_id로 변환
            if filter_dict['seller_name']:
                filter_dict['user_id'] = product_dao.get_id_from_seller_name(db, filter_dict['seller_name'])

            # Select로 검색하는 값이 한번에 여러개 들어온 경우 에러 return
            select_check_list = [filter_dict['product_name'], filter_dict['product_id'], filter_dict['code']]
            if select_check_list.count(None) == 0 or select_check_list.count(None) == 1:
                return jsonify(message = "DATA_ERROR"), 400

        # 권한이 셀러인 경우의 필터 조건 생성
        if role_id == SELLER_ROLE_ID:
            filter_list = ['start_period', 'end_period', 'product_name', 'product_id', 'code', 'on_sale', 'on_list', 'discount']
            for filter_key in filter_list:
                filter_dict[filter_key] = request.args.get('filter_key', None)

            # 셀러권한인 경우 셀러 아이디를 필터에 추가
            filter_dict['user_id'] = user_id

            # Select로 검색하는 값이 한번에 여러개 들어온 경우 에러 return
            select_check_list = [filter_dict['product_name'], filter_dict['product_id'], filter_dict['code']]
            if select_check_list.count(None) == 0 or select_check_list.count(None) == 1:
                return jsonify(message = "DATA_ERROR"), 400

        if db is None:
            return jsonify(message="DATABASE_INIT_ERROR"), 500

        if main_dao.role(db, role_id) is None:
            return jsonify(message="DATA_DOES_NOT_EXIST"), 404

        products_data = product_dao.product_list(db, filter_dict)
        quantity = product_dao.count_product_list(db, filter_dict)

        product_list = {
            "quantity": quantity,
            "product": [{
                "created_at": product['create_at'],
                "image": product_dao.find_first_image(db, product['id']),
                "product_name": product['name'],
                "product_code": product['code'],
                "product_id" : product['product_id'],
                "seller_attribute": product_dao.find_seller_attribute(db, product['seller_attribute_id']),
                "seller_name": product['seller_name'],
                "price": product['price'],
                "discount_price": product['discount_price'] if product['discount_price'] else product['price'],
                "discount_rate": product['discount_rate'],
                "on_sale": product['on_sale'],
                "on_list": product['on_list'],
    	        "discount": 0 if product['discount_rate'] == 0 else 1
                    } for product in products_data]}

        return jsonify(data = product_list), 200

    except pymysql.err.InternalError:
        return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
    except pymysql.err.OperationalError:
        return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
    except pymysql.err.ProgrammingError:
        return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
    except pymysql.err.IntegrityError:
        return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
    except pymysql.err.DataError:
        return jsonify(message="DATA_ERROR"), 400
    except KeyError:
        return jsonify(message="KEY_ERROR"), 400
    except ValidationError as e:
         error_path = str(e.path)[8:-3]
         return jsonify(message=f"{error_path.upper()}_VALIDATION_ERROR"), 400
    except Exception as e:
        return jsonify(message=f"{e}"), 500
    finally:
        if db:
            db.close()
def change_product_status(**kwargs):
    """상품 상태 변경 API
        API 작성:
            최진아

        Header:
            Authorizaion: jwt

        Args:
            code : 상품 코드
            on_sale: 판매여부
            on_list: 진열여부

        Returns:
            {message: ''}, http status code

        Exceptions:
            InternalError: DATABASE가 존재하지 않을 때 발생
            OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
            ProgramingError: SQL syntax가 잘못되었을 때 발생
            IntegrityError: Key의 무결성을 해쳤을 때 발생
            DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
            KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
            ValidationError : 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
    """

    db = None
    try:
        validate(request.json, PRODUCT_STATUS_SCHEMA)
        # 상품 코드를 이용하여 이전의 데이터 및 정보  불러오기
        product_code=request.json['product_code']

        db = get_db_connector()

        previous_product_detail_id = product_dao.find_product(db, product_code)['id']
        previous_data = product_dao.find_product(db, product_code)
        product_detail_id = previous_data['id']

        images_data = product_dao.find_images(db, product_detail_id)
        options_data = product_dao.find_options(db, product_detail_id)
        tags_data = product_dao.find_product_tags(db, product_detail_id)

        # 변경 값 받아와서 이전 값에서 변경하기
        on_sale = request.json.get('on_sale', None)
        on_list = request.json.get('on_list', None)

        if on_sale is not None:
            if not (on_sale == 1 or on_sale == 0) :
                return jsonify(message = "DATA_ERROR"), 400
            previous_data['on_sale'] = on_sale

        if on_list is not None:
            if not (on_list == 1 or on_list == 0):
                return jsonify(message = "DATA_ERROR"), 400
            previous_data['on_list'] = on_list

        db.begin()
        # 변경된 데이터 삽입 후 삽입 된 번호 return
        product_detail_id = product_dao.insert_product_details(db, previous_data)

        # 이전 product_detail의 enddate 날짜 변경
        previous_enddate = product_dao.find_product_date(db,product_detail_id)
        product_dao.change_product_date(db, previous_enddate, previous_product_detail_id)

        # 리스트로 들어온 태그 데이터 삽입
        for tag in tags_data:
            tag_id = product_dao.find_tag_id(db, tag['name'])['id']
            product_dao.insert_product_tag(db, product_detail_id, tag_id)

        # 리스트로 들어온 imgae_data 삽입
        for image in images_data:
            large_url = image['large_url']
            medium_url = image['medium_url']
            small_url = image['small_url']
            list_order = image['list_order']
            image_id = product_dao.insert_image(db, large_url, medium_url, small_url)
            product_dao.insert_product_images(db, product_detail_id, image_id, list_order)

        # 리스트로 들어온 option_data 추가
        for option in options_data:
            color_id = option['color_id']
            size_id = option['size_id']
            stock = option['stock']
            code = option['code']
            product_dao.insert_options(db, product_detail_id, color_id, size_id, stock, code)

        db.commit()
        return (''), 200

    except pymysql.err.InternalError:
        db.rollback()
        return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
    except pymysql.err.OperationalError:
        db.rollback()
        return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
    except pymysql.err.ProgrammingError:
        db.rollback()
        return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
    except pymysql.err.IntegrityError:
        db.rollback()
        return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
    except pymysql.err.DataError:
        db.rollback()
        return jsonify(message="DATA_ERROR"), 400
    except KeyError:
        db.rollback()
        return jsonify(message=f"KEY_ERROR"), 400
    except ValidationError as e:
        error_path = str(e.path)[8:-3]
        return jsonify(message=f"{error_path.upper()}_VALIDATION_ERROR"), 400
    except Exception as e:
        db.rollback()
        return jsonify(message=f"{e}"), 500
    finally:
        if db:
            db.close()
def change_product_information(**kwargs):
    """상품 수정 API
        API 작성:
            최진아

        Header:
            Authorizaion: jwt

        Args:
            "seller_id" : 셀러 아이디,
            "product_code": 상품코드,
            "on_sale": 판매여부,
            "on_list": 진열여부,
            "first_category_id": 1차 카테고리,
            "second_category_id": 2차 카테고리,
            "manufacturer": 제조사,
            "manufacture_date": 제조일자,
            "manufacture_country_id": 원산지 id,
            "name": 상품명,
            "description_short": 한줄 상품 설명,
            "images": {
                        "url": 이미지 url
                        }
            "color_filter_id": 색상필터(썸네일 이미지),
            "style_filter_id": 스타일필터,
            "description_detail": 상세 상품 정보,
            "option": {
                        "code": 옵션 상품 코드,
                        "color_name": 옵션 색상 이,
                        "size_name": 옵션 size 이름,
                        "stock": 재고 수량
                      }
            "price": 판매가,
            "discount_rate": 할인율,
            "discount_price": 할인판매가,
            "discount_start": 할인기간 시작일,
            "discount_end": 할인기간 종료일,
            "min_sales_unit": 최소판매수량,
            "max_sales_unit": 최대판매수량,
            "tag" : {
                        "name": 상품 태그
                    }

        Returns:
            {message: ''}, http status code

        Exceptions:
            InternalError: DATABASE가 존재하지 않을 때 발생
            OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
            ProgramingError: SQL syntax가 잘못되었을 때 발생
            IntegrityError: Key의 무결성을 해쳤을 때 발생
            DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
            KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
            ValidationError : 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
    """

    db = None
    try:
        validate(request.json, CHANGE_PRODUCT_SCHEMA)
        data = request.json

        if data['max_sales_unit'] is None:
            data['max_sales_unit'] = 20

        if data['min_sales_unit'] is None:
            data['min_sales_unit'] = 1

        db = get_db_connector()
        if db is None:
            return jsonify(message="DATABASE_INIT_ERROR"), 500

        data['modifier_id'] = kwargs['user_id']
        product_code = data['product_code']

        # 상품 코드를 이용하여 product_id를 구하고 data에 key,value 추가
        product_id = product_dao.find_product(db, product_code)['product_id']
        previous_product_detail_id = product_dao.find_product(db, product_code)['id']

        data['product_id'] = product_id

        tag_data = data['tag']
        image_data = data['images']
        option_data = data['option']

        # 이미지가 5개를 넘어서 들어오는 경우
        if len(image_data) >= 6:
            return jsonify(message = "DATA_ERROR"), 400

        # 옵션 중복 값 확인
        option_duplicate_check=[]
        # (color_name,size_name)쌍으로 중복 체크
        for option in option_data:
            if ((option['color_name'],option['size_name'])) in option_duplicate_check:
                return jsonify(message = "DATA_ERROR"), 400
            else:
                option_duplicate_check.append((option['color_name'],option['size_name']))

        # 기존의 옵션 코드에 저장된 내용과 현재 옵션값으로 받아온 정보가 다른 경우 체크
        for option in option_data:
            if option['code']:
                option_details=product_dao.find_option_code(db, int(option['code']))
                if (option_details['size_id'],option_details['color_id']) != (product_dao.get_option_size_id(db,option['size_id']),product_dao.get_option_color_id(db, option['color_id'])):
                    return jsonify(message = "DATA_ERROR"), 400

        # 최소 판매 수량이 20개를 초과한 경우 에러
        if data['min_sales_unit'] > 20:
            return jsonify(message="DATA_ERROR"), 400

        # 최대 판매 수량이 20개를 초과한 경우 에러
        if data['max_sales_unit'] > 20:
            return jsonify(message="DATA_ERROR"), 400

        # required가 아닌 항목이 Null값으로도 들어오지 않은 경우 처리
        if 'description_short' not in data:
            data['descriotion_short'] = None
        if 'discount_rate' not in data:
            data['discount_rate'] = 0
        if 'discount_price' not in data:
            data['discount_price'] = None
        if 'discount_start' not in data:
            data['discount_start'] = None
        if 'discount_end' not in data:
            data['discount_end'] = None

        # 상품 정보 고시 에러확인
        manufacture_list = [data['manufacture_country_id'], data['manufacturer'], data['manufacture_date']]
        # 직접 입력인 경우 None이 존재하면 안됨
        if manufacture_list.count(None) == 1 or manufacture_list.count(None) == 2:
            return jsonify(message = "DATA_ERROR"), 400

        # 아래에서 data 입력위해 불필요한 list_data 삭제
        rm_data = ['images','option','tag']
        for rm in rm_data:
            del data[rm]

        price = data['price']
        discount_rate = data['discount_rate']
        discount_price = data['discount_price']

        # 할인율이 없는데 할인가가 있는 경우 에러 return
        if discount_rate == 0 and discount_price is not None:
            return jsonify(message = "DATA_ERROR"), 400
        # 할인율이 음수인 경우 에러 return
        elif discount_rate < 0:
            return jsonify(message = "DATA_ERROR"), 400
        # 할인율이 100%가 넘는 경우 에러 return
        elif discount_rate >= 100:
            return jsonify(message = "DATA_ERROR"), 400
        # 할인율이 있고 할인가가 없는 경우 할인가 계산
        elif discount_rate !=0 and discount_price is None:
            discount_data = math.floor(price*((100-discount_rate)/100)/10)*10
            data['discount_price'] = int(discount_data)

        db.begin()
        product_change_service(db, previous_product_detail_id, data, tag_data, image_data, option_data)
        db.commit()
        return (''), 200

    except pymysql.err.InternalError:
        db.rollback()
        return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
    except pymysql.err.OperationalError:
        db.rollback()
        return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
    except pymysql.err.ProgrammingError:
        db.rollback()
        return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
    except pymysql.err.IntegrityError:
        db.rollback()
        return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
    except pymysql.err.DataError:
        db.rollback()
        return jsonify(message="DATA_ERROR"), 400
    except KeyError:
        db.rollback()
        return jsonify(message=f"KEY_ERROR"), 400
    except ValidationError as e:
        error_path = str(e.path)[8:-3]
        return jsonify(message=f"{error_path.upper()}_VALIDATION_ERROR"), 400
    except Exception as e:
        db.rollback()
        return jsonify(message=f"{e}"), 500
    finally:
        if db:
            db.close()
def history(**kwargs):
    """상품 수정의 수정 이력 API
        API 작성:
            최진아

        Header:
            Authorizaion: jwt

        Args:
             code : 상품 코드

        Returns:
             {data : history_list}, http status code

        Exceptions:
            InternalError: DATABASE가 존재하지 않을 때 발생
            OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
            ProgramingError: SQL syntax가 잘못되었을 때 발생
            IntegrityError: Key의 무결성을 해쳤을 때 발생
            DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
            KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
    """

    db = None
    try:
        db = get_db_connector()
        if db is None:
            return jsonify(message="DATABASE_INIT_ERROR"), 500

        product_code=request.args.get('code')

        role_id = kwargs['role_id']

        # 마스터 권한 전용이므로 마스터가 아닌 경우 요청 drop
        if role_id == SELLER_ROLE_ID:
            return jsonify(message="UNAUTHORIZED"), 401
        # 권한 정보를 찾을 수 없을 때
        if main_dao.role(db, role_id) is None:
            return jsonify(message="DATA_DOES_NOT_EXIST"), 404

        if role_id == MASTER_ROLE_ID:
            history_data = product_dao.find_product_history(db, product_code)
            history_list =[ {
                "modified_data" : history['startdate'],
                "on_sale": history['on_sale'],
                "on_list": history['on_list'],
                "price": history['price'],
                "discount_price": history['discount_price'] if history['discount_price'] else history['price'],
                "discount_rate": history['discount_rate'] if history['discount_rate'] else 0,
                "modifier": user_dao.get_account_from_id(db, history['modifier_id']),
                "group": "브랜디" }
                    for history in history_data]

            return jsonify(data=history_list), 200

    except pymysql.err.InternalError:
        return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
    except pymysql.err.OperationalError:
        return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
    except pymysql.err.ProgrammingError:
        return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
    except pymysql.err.IntegrityError:
        return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
    except pymysql.err.DataError:
        return jsonify(message="DATA_ERROR"), 400
    except KeyError:
        return jsonify(message="KEY_ERROR"), 400
    except Exception as e:
        return jsonify(message=f"{e}"), 500
    finally:
        if db:
            db.close()
    def get(self, **kwargs):
        """회원정보 수정 페이지의 값을 뿌려주는 API
            API 작성:
                손진현

            Header:
                Authorizaion: jwt

            URL params:
                <string:user_account>: 마스터권한일 경우 대상


            Returns:
                {
                    message: STATUS_MESSAGE
                    token: JWT_TOKEN
                    },
                http status code

            Exceptions:
                InternalError: DATABASE가 존재하지 않을 때 발생
                OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
                ProgramingError: SQL syntax가 잘못되었을 때 발생
                IntegrityError: 컬럼의 무결성을 해쳤을 때 발생
                DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
                KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
        """
        try:
            db = get_db_connector()
            if db is None:
                return jsonify(message="DATABASE_INIT_ERROR"), 500

            # master 권한일 경우 urlparameter에서 대상 account를 가져오고 account에 해당하는 user_id를 가져온다
            if kwargs['role_id'] == self.MASTER_ROLE_ID:
                user_account = kwargs.get('user_account', '')
                user_id = user_dao.get_id_from_account(db, user_account)
            # seller 권한일 경우 token에서 user_id를 가져오고 id에 해당하는 account를 가져온다
            elif kwargs['role_id'] == self.SELLER_ROLE_ID:
                user_id = kwargs['user_id']
                user_account = user_dao.get_account_from_id(db, user_id)
            # get_id_from_account, get_account_from_id중 하나라도 제대로 동작하지 않았을 경우 400
            if user_account is None or user_id is None:
                return jsonify(message="INVALID_REQUEST"), 400

            result = get_user_data_service(db, user_id, user_account,
                                           kwargs['role_id'])

            return jsonify(user_data_formatter(*result)), 200

        except pymysql.err.INVALID_REQUESTternalError:
            db.rollback()
            return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
        except pymysql.err.OperationalError:
            db.rollback()
            return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
        except pymysql.err.ProgrammingError:
            db.rollback()
            return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
        except pymysql.err.IntegrityError:
            db.rollback()
            return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
        except pymysql.err.DataError:
            db.rollback()
            return jsonify(message="DATA_ERROR"), 400
        except KeyError:
            db.rollback()
            return jsonify(message="KEY_ERROR"), 400
        except Exception as e:
            db.rollback()
            return jsonify(message=f"{e}"), 500
        finally:
            if db:
                db.close()
def get_product_information(**kwargs):
    """ 상품 수정시 기본 정보 보내주는 API
        API 작성:
            최진아

        Header:
            Authorizaion: jwt

        URL params:
            <string:product_code>: 상품 코드

        Args:
             product_code : 상품 코드,

        Returns:
             {data : product_data}, http status code

        Exceptions:
            InternalError: DATABASE가 존재하지 않을 때 발생
            OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
            ProgramingError: SQL syntax가 잘못되었을 때 발생
            IntegrityError: Key의 무결성을 해쳤을 때 발생
            DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
            KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생

    """
    db = None
    try:
        db = get_db_connector()
        if db is None:
            return jsonify(message="DATABASE_INIT_ERROR"), 500

        product_code=request.args.get('code')
        data = product_dao.find_product(db, product_code)

        seller_id = product_dao.get_seller_from_code(db, product_code)
        first_category_id = data['first_category_id']
        second_category_id = data['second_category_id']
        product_detail_id = data['id']

        category_data = product_dao.find_category(db, first_category_id, second_category_id)
        images_data = product_dao.find_images(db, product_detail_id)
        options_data = product_dao.find_options(db, product_detail_id)
        tags_data = product_dao.find_product_tags(db, product_detail_id)

        product_data = product_data_service(db, seller_id, product_code, data, category_data, images_data, options_data, tags_data)
        return jsonify(data=product_data), 200

    except pymysql.err.InternalError:
        return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
    except pymysql.err.OperationalError:
        return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
    except pymysql.err.ProgrammingError:
        return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
    except pymysql.err.IntegrityError:
        return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
    except pymysql.err.DataError:
        return jsonify(message="DATA_ERROR"), 400
    except KeyError:
        return jsonify(message="KEY_ERROR"), 400
    except Exception as e:
        return jsonify(message=f"{e}"), 500
    finally:
        if db:
            db.close()
def save_product(**kwargs):
    """ 상품등록 API
        API 작성:
            최진아

        Header:
            Authorizaion: jwt

        Args:
           "seller_id": 판매자 id,
           "on_sale": 판매여부,
           "on_list": 진열여부,
           "first_category_id": 1차 카테고리,
           "second_category_id": 2차 카테고리,
           "manufacturer": 제조사,
           "manufacture_date": 제조일자,
           "manufacture_country_id": 원산지 id,
           "name": 상품명,
           "description_short": 한줄 상품 설명,
           "images": {
                        "url": 이미지 url
                     }
           "color_filter_id": 색상필터(썸네일 이미지),
           "style_filter_id": 스타일필터,름
           "description_detail": 상세 상품 정보,
           "option": {
                        "color_name": 름,
                        "size_name": 옵션 size 이름,
                        "stock": 재고 수량
                     }
          "price": 판매가,
          "discount_rate": 할인율,
          "discount_price": 할인판매가,
          "discount_start": 할인기간 시작일,
          "discount_end": 할인기간 종료일,
          "min_sales_unit": 최소판매수량,
          "max_sales_unit": 최대판매수량,
          "tag" : {
                        "name": 상품 태
                  }

        Returns:
            {message: ''}, http status code

        Exceptions:
            InternalError: DATABASE가 존재하지 않을 때 발생
            OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
            ProgramingError: SQL syntax가 잘못되었을 때 발생
            IntegrityError: Key의 무결성을 해쳤을 때 발생
            DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
            KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
            ValidationError : 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
    """

    db = None
    try:
        validate(request.json, PRODUCT_SCHEMA)
        data = request.json

        db = get_db_connector()
        if db is None:
            return jsonify(message="DATABASE_INIT_ERROR"), 500

        user_id = kwargs['user_id']
        role_id = kwargs['role_id']

        product_number = str(product_dao.count_product(db) + 1)
        code = "SB" + product_number.zfill(18)

        # 권한이 Master인 경우 seller_id는 data에서 들어온 seller_id
        if role_id == MASTER_ROLE_ID:
            seller_id = data['seller_id']
        # 권한이 Seller인 경우 seller_id는user_id
        elif role_id == SELLER_ROLE_ID:
            seller_id = user_id
        elif main_dao.role(db, role_id) is None:
            return jsonify(message="DATA_DOES_NOT_EXIST"), 404

        tag_data = data['tag']
        image_data = data['images']
        option_data = data['option']

        # 이미지가 5개를 넘어서 들어오는 경우
        if len(image_data) >= 6:
            return jsonify(message="DATA_ERROR"), 400

        # 옵션 중복 값 확인
        option_duplicate_check = []
        # (color_name,size_name)쌍으로 중복 체크
        for option in option_data:
            if ((option['color_name'],
                 option['size_name'])) in option_duplicate_check:
                return jsonify(message="DATA_ERROR"), 400
            else:
                option_duplicate_check.append(
                    (option['color_name'], option['size_name']))

        # 최소 판매 수량이 20개를 초과한 경우 에러
        if data['min_sales_unit'] > 20:
            return jsonify(message="DATA_ERROR"), 400

        # 최대 판매 수량이 20개를 초과한 경우 에러
        if data['max_sales_unit'] > 20:
            return jsonify(message="DATA_ERROR"), 400

        # required가 아닌 항목이 Null값으로도 들어오지 않은 경우 처리
        if 'description_short' not in data:
            data['descriotion_short'] = None
        if 'discount_rate' not in data:
            data['discount_rate'] = 0
        if 'discount_price' not in data:
            data['discount_price'] = None
        if 'discount_start' not in data:
            data['discount_start'] = None
        if 'discount_end' not in data:
            data['discount_end'] = None

        # 상품 정보 고시 에러확인
        manufacture_list = [
            data['manufacture_country_id'], data['manufacturer'],
            data['manufacture_date']
        ]
        # 직접 입력인 경우 None이 존재하면 안됨
        if manufacture_list.count(None) == 1 or manufacture_list.count(
                None) == 2:
            return jsonify(message="DATA_ERROR"), 400

        # 아래에서 data 입력위해 불필요한 list_data 삭제
        rm_data = ['images', 'option', 'tag']
        for rm in rm_data:
            del data[rm]

        price = data['price']
        discount_rate = data['discount_rate']
        discount_price = data['discount_price']

        # 할인율이 없는데 할인가가 있는 경우 에러 return
        if discount_rate == 0 and discount_price is not None:
            return jsonify(message="DATA_ERROR"), 400
        # 할인율이 음수인 경우 에러 return
        if discount_rate < 0:
            return jsonify(message="DATA_ERROR"), 400
        # 할인율이 100%가 넘는 경우 에러 return
        if discount_rate >= 100:
            return jsonify(message="DATA_ERROR"), 400
        # 할인율이 있고 할인가가 없는 경우 할인가 계산
        elif discount_rate != 0 and discount_price is None:
            discount_data = math.floor(price *
                                       ((100 - discount_rate) / 100) / 10) * 10
            data['discount_price'] = int(discount_data)

        db.begin()
        product_save_service(db, data, seller_id, user_id, code, tag_data,
                             image_data, option_data)
        db.commit()

        return jsonify(message="SUCCESS"), 200

    except pymysql.err.InternalError:
        db.rollback()
        return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
    except pymysql.err.OperationalError:
        db.rollback()
        return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
    except pymysql.err.ProgrammingError:
        db.rollback()
        return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
    except pymysql.err.IntegrityError:
        db.rollback()
        return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
    except pymysql.err.DataError:
        db.rollback()
        return jsonify(message="DATA_ERROR"), 400
    except KeyError:
        db.rollback()
        return jsonify(message=f"KEY_ERROR"), 400
    except ValidationError as e:
        error_path = str(e.path)[8:-3]
        return jsonify(message=f"{error_path.upper()}_VALIDATION_ERROR"), 400
    except Exception as e:
        db.rollback()
        return jsonify(message=f"{e}"), 500
    finally:
        if db:
            db.close()
def product_information(**kwargs):
    """상품 등록시 옵션 및 필터 정보 전달 API
        API 작성:
            최진아

        Header:
            Authorizaion: jwt

        Returns:
             {data : information_data}, http status code

        Exceptions:
            InternalError: DATABASE가 존재하지 않을 때 발생
            OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
            ProgramingError: SQL syntax가 잘못되었을 때 발생
            IntegrityError: Key의 무결성을 해쳤을 때 발생
            DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
            KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생

    """

    db = None
    try:
        db = get_db_connector()
        if db is None:
            return jsonify(message="DATABASE_INIT_ERROR"), 500

        countries = product_dao.country_data(db)
        colors = product_dao.option_color(db)
        sizes = product_dao.option_size(db)
        color_filters = product_dao.color_filter(db)
        style_filters = product_dao.style_filter(db)

        information_data = [{
            "country": [{
                "id": country.get('id'),
                "name": country.get('name')} for country in countries],
            "option_color": [{
                "id": color.get('id'),
                "name": color.get('name')} for color in colors],
            "option_size": [{
                "id": size.get('id'),
                "name": size.get('name')} for size in sizes],
            "color_filter": [{
                "id": color_data.get('id'),
                "name": color_data.get('name'),
                "name_eng": color_data.get('name_eng'),
                "image_url": color_data.get('image_url')} for color_data in color_filters],
            "style_filter": [{
                "id": style_data.get('id'),
                "name": style_data.get('name')} for style_data in style_filters]}]

        return jsonify(data=information_data), 200

    except pymysql.err.InternalError:
        return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
    except pymysql.err.OperationalError:
        return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
    except pymysql.err.ProgrammingError:
        return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
    except pymysql.err.IntegrityError:
        return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
    except pymysql.err.DataError:
        return jsonify(message="DATA_ERROR"), 400
    except KeyError:
        return jsonify(message="KEY_ERROR"), 400
    except Exception as e:
        return jsonify(message=f"{e}"), 500
    finally:
        if db:
            db.close()
    def post(self):
        """회원가입 API
        API 작성:
            손진현

        Args:
            account: 계정명
            password: 비밀번호
            seller_name: 셀러명
            seller_name_eng: 셀러명(영문)
            cs_number: 고객센터 전화번호
            seller_attribute_id: 셀러 속성 id
            site_url: 셀러 사이트 url

        Returns:
            {message: STATUS_MESSAGE}, http status code

        Exceptions:
            InternalError: DATABASE가 존재하지 않을 때 발생
            OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
            ProgramingError: SQL syntax가 잘못되었을 때 발생
            IntegrityError: Key의 무결성을 해쳤을 때 발생
            DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
            ValidationError : 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
        """

        db = None
        try:
            # JSON SCHEMA를 이용한 Validation
            validate(request.json, SIGN_UP_SCHEMA)
            data = request.json

            # DB 커넥터 정의 및 에러 핸들
            db = get_db_connector()
            if db is None:
                return jsonify(message="DATABASE_INIT_ERROR"), 500

            # 입력받은 acount로 중복된 유저인지 조회
            user_id = user_dao.get_id_from_account(db, data['account'])
            if user_id:
                return jsonify(message="ACCOUNT_DUPLICATED"), 409

            # bcrypt 라이브러리를 이용하여 비밀번호를 SHA256으로 해
            data['password'] = bcrypt.hashpw(data['password'].encode('utf-8'),
                                             bcrypt.gensalt()).decode('utf-8')

            db.begin()
            sign_up_service(db, data)
            db.commit()

            return jsonify(message="SIGN_UP_COMPLETE"), 200

        except pymysql.err.InternalError:
            db.rollback()
            return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
        except pymysql.err.OperationalError:
            db.rollback()
            return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
        except pymysql.err.ProgrammingError:
            db.rollback()
            return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
        except pymysql.err.IntegrityError:
            db.rollback()
            return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
        except pymysql.err.DataError:
            db.rollback()
            return jsonify(message="DATA_ERROR"), 400
        except ValidationError as e:
            error_path = str(e.path)[8:-3]
            return jsonify(
                message=f"{error_path.upper()}_VALIDATION_ERROR"), 400
        except Exception as e:
            db.rollback()
            return jsonify(message=f"{e}"), 500
        finally:
            if db:
                db.close()
def user_status(**kwargs):
    """마스터 유저의 셀러 정보 수정 페이지의 액션 버튼을 통해 셀러의 상태를 조정하는 API
                API 작성:
                    손진현

                Headers:
                    Authorizaion: jwt

                Url Params:
                    <string:user_account>: 대상 user의 id

                Body:
                    action: 유저에게 적용할 action id

                Returns:
                    {
                        message: STATUS_MESSAGE
                        token: JWT_TOKEN
                        },
                    http status code

                Exceptions:
                    InternalError: DATABASE가 존재하지 않을 때 발생
                    OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
                    ProgramingError: SQL syntax가 잘못되었을 때 발생
                    IntegrityError: 컬럼의 무결성을 해쳤을 때 발생
                    UserNotExistError: urlparams로 전달받은 seller가 존재하지 않을 때
                    WrongActionError: seller의 현재 상태에 적용되지 않는 action 버튼일 때
                    DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
                    KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
            """
    db = None
    try:
        db = get_db_connector()
        if db is None:
            return jsonify(message="DATABASE_INIT_ERROR"), 500

        # 마스터 권한 전용 메뉴이므로 마스터 토큰이 아닐 경우 요청 drop
        if not kwargs['role_id'] == User.MASTER_ROLE_ID:
            return jsonify(message="NOT_AUTHORIZED_USER"), 403

        # 해당 유저에게 유효한 액션인지 확인
        user_status_update_validate_service(db, request.json['action'],
                                            kwargs['target_id'])

        # user_id : url params로 전달된 변경할 대상 유저의 id값
        # modifier_id : 토큰으로부터 추출된 master의 id값
        # action : query string으로 전달된 유저에 적용될 action id값
        db.begin()
        user_status_update_service(db,
                                   user_id=kwargs['target_id'],
                                   modifier_id=kwargs['user_id'],
                                   action=request.json['action'])
        db.commit()

        return jsonify(''), 200

    except pymysql.err.InternalError:
        db.rollback()
        return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
    except pymysql.err.OperationalError:
        db.rollback()
        return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
    except pymysql.err.ProgrammingError:
        db.rollback()
        return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
    except pymysql.err.IntegrityError:
        db.rollback()
        return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
    except pymysql.err.DataError:
        db.rollback()
        return jsonify(message="DATA_ERROR"), 400
    except UserNotExistError:
        db.rollback()
        return jsonify(message="USER_DOES_NOT_EXIST"), 400
    except WrongActionError:
        db.rollback()
        return jsonify(message="USER_DOES_NOT_SUPPORT_THIS_ACTION"), 400
    except KeyError:
        db.rollback()
        return jsonify(message="KEY_ERROR"), 400
    except Exception as e:
        db.rollback()
        return jsonify(message=f"{e}"), 500
    finally:
        if db:
            db.close()
def user_list(**kwargs):
    """마스터 유저의 셀러 정보 수정 페이지의 리스트를 리턴하는 API
                API 작성:
                    손진현

                Header:
                    Authorizaion: jwt

                Query Strings: 필터링 옵션
                    id: 유저 번호
                    account: 셀러 계정
                    seller_name_eng : 셀러 영어 이름
                    seller_name : 셀러 한글 이름
                    manager_name : 담당자 이름
                    seller_status : 셀러 상태
                    manager_phone : 담당자 전화번호
                    manager_email : 담당자 이메일
                    seller_attribute : 셀러 속성


                Returns:
                    {
                        message: STATUS_MESSAGE
                        token: JWT_TOKEN
                        },
                    http status code

                Exceptions:
                    InternalError: DATABASE가 존재하지 않을 때 발생
                    OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
                    ProgramingError: SQL syntax가 잘못되었을 때 발생
                    IntegrityError: 컬럼의 무결성을 해쳤을 때 발생
                    DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
                    KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
            """
    db = None
    try:
        db = get_db_connector()
        if db is None:
            return jsonify(message="DATABASE_INIT_ERROR"), 500

        # 마스터 권한 전용 메뉴이므로 마스터 토큰이 아닐 경우 요청 drop
        if kwargs['role_id'] != User.MASTER_ROLE_ID:
            return jsonify(message="NOT_AUTHORIZED_USER"), 403

        filter_validation_service(request.args)
        lists = get_seller_list_service(db, request.args)

        return jsonify(**lists), 200

    except pymysql.err.INVALID_REQUESTternalError:
        db.rollback()
        return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
    except pymysql.err.OperationalError:
        db.rollback()
        return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
    except pymysql.err.ProgrammingError:
        db.rollback()
        return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
    except pymysql.err.IntegrityError:
        db.rollback()
        return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
    except pymysql.err.DataError:
        db.rollback()
        return jsonify(message="DATA_ERROR"), 400
    except KeyError:
        db.rollback()
        return jsonify(message="KEY_ERROR"), 400
    except Exception as e:
        db.rollback()
        return jsonify(message=f"{e}"), 500
    finally:
        if db:
            db.close()
def sign_in():
    """로그인 API
        API 작성:
            손진현

        Args:
            account: 계정명,
            password: 비밀번호

        Returns:
            {
                message: STATUS_MESSAGE
                token: JWT_TOKEN
                },
            http status code

        Exceptions:
            InternalError: DATABASE가 존재하지 않을 때 발생
            OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
            ProgramingError: SQL syntax가 잘못되었을 때 발생
            IntegrityError: Key의 무결성을 해쳤을 때 발생
            DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
            ValidationError : 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
        """

    db = None
    try:
        # JSON SCHEMA를 이용한 Validation
        validate(request.json, SIGN_IN_SCHEMA)
        data = request.json

        # DB 정의 및 에러 핸들
        db = get_db_connector()
        if db is None:
            return jsonify(message="DATABASE_INIT_ERROR"), 500

        # 액세스 토큰에 담을 role_id, user_id와 비밀번호, 셀러 권한을 페치한다
        result = user_dao.get_id_role_password_status_from_account(
            db, data['account'])

        # account가 존재하지 않아 아무것도 페치되지 않았을 경우 핸들
        if not result:
            return jsonify(message="ACCOUNT_DOES_NOT_EXIST"), 400
        # hash된 password가 일치하지 않을 때 사용
        if not bcrypt.checkpw(data['password'].encode('utf-8'),
                              result['password'].encode('utf-8')):
            return jsonify(message="PASSWORD_MISMATCH"), 400
        # 유저의 role이 셀러이며 status가 입점대기일 때 403 에러 발생
        if (result['role_id'] == User.SELLER_ROLE_ID
                and result['status_id'] == User.BASIC_STATUS_ID):
            return jsonify(message="NOT_AUTHORIZED_USER"), 403

        # jwt 작성
        token = jwt.encode(
            {
                'role_id': result['role_id'],
                'user_id': result['id'],
                'exp': datetime.utcnow() + timedelta(hours=1)
            }, SERCRET, HASH_ALGORITHM)
        return jsonify(message="SIGN_IN_COMPLETE", token=token), 200

    except pymysql.err.InternalError:
        return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
    except pymysql.err.OperationalError:
        return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
    except pymysql.err.ProgrammingError:
        return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
    except pymysql.err.IntegrityError:
        return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
    except pymysql.err.DataError:
        return jsonify(message="DATA_ERROR"), 400
    except ValidationError as e:
        error_path = str(e.path)[8:-3]
        return jsonify(message=f"{error_path.upper()}_VALIDATION_ERROR"), 400
    except Exception as e:
        return jsonify(message=f"{e}"), 500
    finally:
        if db:
            db.close()
    def put(self, **kwargs):
        """회원정보 수정 페이지에서 입력받은 값으로 회원정보를 수정하는 API
            API 작성:
                손진현

            Header:
                Authorizaion: jwt

            Args:
                profile_image: 프로필 이미지(url),
                seller_attribute: 셀러 속성 id,
                seller_name: 셀러 이름,
                seller_name_eng: 셀러 영어 이름,
                seller_account: 셀러 계정,
                background_image: 배경 이미지(url),
                introduction_short: 셀러 한줄 소개,
                introduction_detail: 셀러 상세 소개,
                site_url: 홈페이지,
                manager: {
                                "name: 담당자 이름,
                                "phone": 담당자 전화번호,
                                "email": 담당자 이메일
                            }
                cs_phone: 고객센터 전화번호,
                zip_code: 우편번호,
                address: 주소,
                address_detail: 상세 주소,
                weekday_start_time: 고객센터 운영시작시간(주중),
                weekday_end_time: 고객센터 운영종료시간(주중),
                weekend_start_time: 고객센터 운영시작시간(주말),
                weekend_end_time: 고객센터 운영시작시간(주말),
                bank: 정산은행,
                bank_account_name: 예금주,
                bank_account_number: 계좌번호
                height: 모델 키,
                top_size: 모델 상의 사이즈,
                bottom_size: 모델 하의 사이즈,
                foot_size: 모델 발 사이즈

            Returns:
                {message: STATUS_MESSAGE}, http status code

            Exceptions:
                InternalError: DATABASE가 존재하지 않을 때 발생
                OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
                ProgramingError: SQL syntax가 잘못되었을 때 발생
                IntegrityError: 컬럼의 무결성을 해쳤을 때 발생
                DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
                KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
        """

        try:
            db = get_db_connector()
            if db is None:
                return jsonify(message="DATABASE_INIT_ERROR"), 500

            # master 권한일 경우에 대한 validation 및 urlparameter에서 가져온 account에 해당하는 user_id를 조회
            if kwargs['role_id'] == self.MASTER_ROLE_ID:
                validate(request.json, USER_DATA_MODIFY_MASTER)
                user_id = user_dao.get_id_from_account(db,
                                                       kwargs['user_account'])
                modifier_id = kwargs['user_id']
            # seller 권한일 경우에 대한 validation 및 token에서 user_id를 조회
            elif kwargs['role_id'] == self.SELLER_ROLE_ID:
                validate(request.json, USER_DATA_MODIFY_SELLER)
                user_id = kwargs['user_id']
                modifier_id = user_id
            # user_id가 존재하지 않을 경우 유효하지 않은 동작으로 400 출력
            if user_id is None:
                return jsonify(message="INVALID_REQUEST"), 400

            # request로 전달받은 json을 테이블별로 정렬
            details, managers = user_data_deformatter(**request.json)
            db.begin()
            user_update_service(db, user_id, modifier_id, details, managers)
            db.commit()

            return jsonify(''), 200

        except pymysql.err.InternalError:
            db.rollback()
            return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
        except pymysql.err.OperationalError:
            db.rollback()
            return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
        except pymysql.err.ProgrammingError:
            db.rollback()
            return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
        except pymysql.err.IntegrityError:
            db.rollback()
            return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
        except pymysql.err.DataError:
            db.rollback()
            return jsonify(message="DATA_ERROR"), 400
        except KeyError:
            db.rollback()
            return jsonify(message="KEY_ERROR"), 400
        except Exception as e:
            db.rollback()
            return jsonify(message=f"{e}"), 500
        finally:
            if db:
                db.close()
Exemple #15
0
import os
import sys
import pymysql

ROOT_DIR = os.path.dirname(os.path.abspath("API"))
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.extend([ROOT_DIR])
os.chdir(BASE_DIR)

from create_table_utils import init_database, import_aquery_to_list
from connections import get_db_connector

db = get_db_connector()
cursor = db.cursor()

db.begin()
init_database(db)

with open('aquery_exports/brandi_20200612_28_25.txt', 'r') as aquery_file:
    TABLE_QUERIES = import_aquery_to_list(aquery_file)

for query in TABLE_QUERIES:
    cursor.execute(query)

db.commit()
cursor.close()
db.close()
print('COMPLETE')
def product_category(**kwargs):
    """상품 등록시 카테고리 정보 전달 API
        API 작성:
            최진아

        Header:
            Authorizaion: jwt

        Args:
             user_id: 접속 아이디,
             seller_id : 셀러 아이디,
             attribute_group_id: 판매자 속성

        Returns:
             {data : category_list}, http status code

        Exceptions:
            InternalError: DATABASE가 존재하지 않을 때 발생
            OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
            ProgramingError: SQL syntax가 잘못되었을 때 발생
            IntegrityError: Key의 무결성을 해쳤을 때 발생
            DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
            KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
    """

    db = None
    try:
        db = get_db_connector()
        if db is None:
            return jsonify(message="DATABASE_INIT_ERROR"), 500

        user_id = kwargs['user_id']
        role_id = kwargs['role_id']

        if role_id == MASTER_ROLE_ID:
            seller_id = request.args.get('seller_id')
            attribute_group_id = product_dao.get_attribute_group_id(db, seller_id)
        elif role_id == SELLER_ROLE_ID :
            attribute_group_id = product_dao.get_attribute_group_id(db, user_id)
        elif main_dao.role(db, role_id) is None:
            return jsonify(message="DATA_DOES_NOT_EXIST"), 404

        first_category_data = product_dao.first_category(db, attribute_group_id)

        category_list = [{
            "id": category.get('id'),
            "name": category.get('name'),
            "second_category": [{
                "id":category_detail.get('id'),
                "name":category_detail.get('name')
            }for category_detail in product_dao.second_category(db,category.get('id'))]
        }for category in first_category_data]
        return jsonify(data=category_list), 200

    except pymysql.err.InternalError:
        return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
    except pymysql.err.OperationalError:
        return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
    except pymysql.err.ProgrammingError:
        return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
    except pymysql.err.IntegrityError:
        return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
    except pymysql.err.DataError:
        return jsonify(message="DATA_ERROR"), 400
    except KeyError:
        return jsonify(message="KEY_ERROR"), 400
    except Exception as e:
        return jsonify(message=f"{e}"), 500
    finally:
        if db:
            db.close()
def category(**kwargs):
    """사이드바 예시 API
    API 작성:
        최진아

    Args:
        role_id : user의 권한 확인

    Returns:
        {data : sidebar_list}, http status code

    Exceptions:
        InternalError: DATABASE가 존재하지 않을 때 발생
        OperationalError: DATABASE 접속이 인가되지 않았을 때 발생
        ProgramingError: SQL syntax가 잘못되었을 때 발생
        IntegrityError: Key의 무결성을 해쳤을 때 발생
        DataError: 컬럼 타입과 매칭되지 않는 값이 DB에 전달되었을 때 발생
        KeyError: 엔드포인트에서 요구하는 키값이 전달되지 않았을 때 발생
    """

    db = None
    try:
        db = get_db_connector()
        if db is None:
            return jsonify(message="DATABASE_INIT_ERROR"), 500
        role_id = kwargs['role_id']

        if main_dao.role(db, role_id) is None:
            return jsonify(message="DATA_DOES_NOT_EXIST"), 404

        data = main_dao.sidebar_list(db, role_id)

        sidebar = [{
            "id":
            side_list.get('id'),
            "name":
            side_list.get('name'),
            "detail_data": [{
                "id": detail.get('id'),
                "name": detail.get('name')
            } for detail in main_dao.sidebar_detail_list(
                db, side_list.get('id'))]
        } for side_list in data]

        return jsonify(data=sidebar), 200

    except pymysql.err.InternalError:
        return jsonify(message="DATABASE_DOES_NOT_EXIST"), 500
    except pymysql.err.OperationalError:
        return jsonify(message="DATABASE_AUTHORIZATION_DENIED"), 500
    except pymysql.err.ProgrammingError:
        return jsonify(message="DATABASE_SYNTAX_ERROR"), 500
    except pymysql.err.IntegrityError:
        return jsonify(message="FOREIGN_KEY_CONSTRAINT_ERROR"), 500
    except pymysql.err.DataError:
        return jsonify(message="DATA_ERROR"), 400
    except KeyError:
        return jsonify(message="KEY_ERROR"), 400
    except Exception as e:
        return jsonify(message=f"{e}"), 500
    finally:
        if db:
            db.close()
Exemple #18
0
import os
import sys

ROOT_DIR = os.path.dirname(os.path.abspath("API"))
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.extend([ROOT_DIR])
os.chdir(BASE_DIR)

from create_table_utils import init_database, import_aquery_to_list
from connections import get_db_connector

db = get_db_connector()
cursor = get_db_connector()

db.begin()
init_database(db)

with open('aquery_exports/brandi_20200530_29_44.txt', 'r') as aquery_file:
    TABLE_QUERIES = import_aquery_to_list(aquery_file)

for query in TABLE_QUERIES:
    cursor.execute(query)

db.commit()
cursor.close()
db.close()
print('COMPLETE')