재고 관리
- 재고 기록: 모든 재고의 위치, 수량, 상태 등을 실시간으로 기록하고 관리합니다.
- 재고 이동: 재고의 이동 기록을 추적하여 정확한 위치 정보를 제공합니다.
- 재고 조정: 재고의 손실, 손상, 반품 등의 이유로 인한 재고 조정을 관리합니다.
연습문제 1~2
문제 1 : 필터링
- 진행상태가 “입고완료”로 되어 있는 레코드 찾기
- 진행상태가 “입고완료”중 화주와 상품종류가 같은 레코드 찾기
- 위 첫 번째와 두 번째 조건을 만족하는 레코드를 최근 저장된 레코드 부터 출력하기
문제 2 : 재고 저장 관리
- 다음과 같은 재고 테이블을 만드시오
재고 관리 실습예제
1. 재고기록 및 조회
다음은 입고 완료된 정보에 대해 재고 기록(입고완료 후 자동으로 기록)을 하고 조회를 하기 위한 요구사항(모든 재고의 위치, 수량, 상태 )을 반영하여 화면설계 및 기능 설계를 한 예제입니다.
- 입고 완료된 레코드 중 재고에 반영된 레코드는 입고테이블에서 재고반영완료로 처리
- 재고 수량의 update는 화주와 상품종류가 같을 때 입고 완료된 입고수량을 재고 수량에 더해서 저장
2. 재고이동 및 재고조정
다음은 재고 완료된 정보에 대해 재고이동은 “적치장소”를 조정, 재고조정(반품등)은 “진행상태”를 조정 반영하여 화면설계 및 기능설계를 한 예제입니다.
- 재고이동 및 재고조정을 위해 GNB에서 재고이동과 재고조정 항목을 재고관리로 수정
디렉토리 구조
site2/
├── app.py
└── templates/
├── enterRegist.html
├── enterView.html
├── stockView.html
└── stockManage.html
app.py
from flask import Flask, render_template, request, redirect, url_for
import mysql.connector
from mysql.connector import Error
from datetime import date
from datetime import datetime
app = Flask(__name__)
# 데이터베이스 연결 설정
def create_connection():
connection = None
try:
connection = mysql.connector.connect(
host='localhost',
user='joon',
password='1234',
database='backend'
)
except Error as e:
print(f"Error: '{e}'")
return connection
# 메인 페이지 라우트
@app.route('/')
def enterRegist():
return render_template('enterRegist.html')
# 데이터 저장 라우트
@app.route('/submit', methods=['POST'])
def submit():
if request.method == 'POST':
consignor = request.form['consignor']
product_type = request.form['product_type']
product_quantity = request.form['product_quantity']
arrival_date = request.form['arrival_date']
arrival_manager = request.form['arrival_manager']
storage_location = request.form['storage_location']
product_status = request.form['product_status']
progress_status = request.form['progress_status']
connection = create_connection()
cursor = connection.cursor()
cursor.execute("""
INSERT INTO incoming (consignor, product_type, product_quantity, arrival_date, arrival_manager, storage_location, product_status, progress_status)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
""", (consignor, product_type, product_quantity, arrival_date, arrival_manager, storage_location, product_status, progress_status))
connection.commit()
cursor.close()
connection.close()
return redirect(url_for('enterRegist'))
def update_stock():
connection = create_connection()
cursor = connection.cursor(dictionary=True)
# 입고 테이블에서 입고완료인 경우만 가져오기
cursor.execute("""
SELECT * FROM incoming WHERE progress_status = '입고완료'
""")
incoming_data = cursor.fetchall()
for row in incoming_data:
consignor = row['consignor']
product_type = row['product_type']
product_quantity = row['product_quantity']
arrival_manager = row['arrival_manager']
storage_location = row['storage_location']
product_status = row['product_status']
progress_status = row['progress_status']
# 재고 테이블에서 동일한 화주와 상품종류가 있는지 확인
cursor.execute("""
SELECT * FROM stock WHERE consignor = %s AND product_type = %s AND storage_location = %s ORDER BY stock_update_date DESC LIMIT 1
""", (consignor, product_type, storage_location))
stock_entry = cursor.fetchone()
if stock_entry:
# 재고 수량을 계산
new_quantity = stock_entry['stock_quantity'] + product_quantity
# 재고 수량 업데이트
cursor.execute("""
UPDATE stock SET stock_quantity = %s, stock_update_date = %s, stock_manager = %s WHERE id = %s
""", (new_quantity, datetime.now(), arrival_manager, stock_entry['id']))
else:
# 재고 테이블에 새로운 레코드 추가
progress_status = "재고"
cursor.execute("""
INSERT INTO stock (consignor, product_type, stock_quantity, stock_update_date, stock_manager, storage_location, product_status, progress_status)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
""", (consignor, product_type, product_quantity, datetime.now(), arrival_manager, storage_location, product_status, progress_status))
# incoming 테이블의 progress_status를 '재고반영완료'로 업데이트
cursor.execute("""
UPDATE incoming SET progress_status = '재고반영완료' WHERE id = %s
""", (row['id'],))
connection.commit()
cursor.close()
connection.close()
# 입고 조회 페이지 라우트
@app.route('/enterView', methods=['GET'])
def enterView():
page = request.args.get('page', 1, type=int)
per_page = 5
consignor = request.args.get('consignor', '')
product_type = request.args.get('product_type', '')
arrival_date = request.args.get('arrival_date', '')
arrival_manager = request.args.get('arrival_manager', '')
progress_status = request.args.get('progress_status', '')
connection = create_connection()
cursor = connection.cursor(dictionary=True)
query = """
SELECT * FROM incoming
WHERE consignor LIKE %s AND product_type LIKE %s AND arrival_date LIKE %s AND arrival_manager LIKE %s AND progress_status LIKE %s
LIMIT %s OFFSET %s
"""
cursor.execute(query, ('%' + consignor + '%', '%' + product_type + '%', '%' + arrival_date + '%', '%' + arrival_manager + '%', '%' + progress_status + '%', per_page, (page-1)*per_page))
results = cursor.fetchall()
cursor.execute("SELECT COUNT(*) FROM incoming WHERE consignor LIKE %s AND product_type LIKE %s AND arrival_date LIKE %s AND arrival_manager LIKE %s AND progress_status LIKE %s",
('%' + consignor + '%', '%' + product_type + '%', '%' + arrival_date + '%', '%' + arrival_manager + '%', '%' + progress_status + '%'))
total = cursor.fetchone()['COUNT(*)']
total_pages = (total + per_page - 1) // per_page
cursor.close()
connection.close()
prev_url = url_for('enterView', page=page-1, consignor=consignor, product_type=product_type, arrival_date=arrival_date, arrival_manager=arrival_manager, progress_status=progress_status) if page > 1 else None
next_url = url_for('enterView', page=page+1, consignor=consignor, product_type=product_type, arrival_date=arrival_date, arrival_manager=arrival_manager, progress_status=progress_status) if page < total_pages else None
return render_template('enterView.html', results=results, total_pages=total_pages, current_page=page, prev_url=prev_url, next_url=next_url,
consignor=consignor, product_type=product_type, arrival_date=arrival_date, arrival_manager=arrival_manager, progress_status=progress_status)
# 재고 조회 페이지 라우트
@app.route('/stockView', methods=['GET'])
def stockView():
update_stock()
page = request.args.get('page', 1, type=int)
per_page = 5
consignor = request.args.get('consignor', '')
product_type = request.args.get('product_type', '')
stock_manager = request.args.get('stock_manager', '')
storage_location = request.args.get('storage_location', '')
product_status = request.args.get('product_status', '')
progress_status = request.args.get('progress_status', '')
connection = create_connection()
cursor = connection.cursor(dictionary=True)
query = """
SELECT * FROM stock
WHERE consignor LIKE %s AND product_type LIKE %s AND stock_manager LIKE %s AND storage_location LIKE %s AND product_status LIKE %s AND progress_status LIKE %s
ORDER BY stock_update_date DESC
LIMIT %s OFFSET %s
"""
cursor.execute(query, ('%' + consignor + '%', '%' + product_type + '%', '%' + stock_manager + '%', '%' + storage_location + '%', '%' + product_status + '%', '%' + progress_status + '%', per_page, (page-1)*per_page))
results = cursor.fetchall()
cursor.execute("SELECT COUNT(*) FROM stock WHERE consignor LIKE %s AND product_type LIKE %s AND stock_manager LIKE %s AND storage_location LIKE %s AND product_status LIKE %s AND progress_status LIKE %s",
('%' + consignor + '%', '%' + product_type + '%', '%' + stock_manager + '%', '%' + storage_location + '%', '%' + product_status + '%', '%' + progress_status + '%'))
total = cursor.fetchone()['COUNT(*)']
total_pages = (total + per_page - 1) // per_page
cursor.close()
connection.close()
prev_url = url_for('stockView', page=page-1, consignor=consignor, product_type=product_type, stock_manager=stock_manager, storage_location=storage_location, product_status=product_status, progress_status=progress_status) if page > 1 else None
next_url = url_for('stockView', page=page+1, consignor=consignor, product_type=product_type, stock_manager=stock_manager, storage_location=storage_location, product_status=product_status, progress_status=progress_status) if page < total_pages else None
return render_template('stockView.html', results=results, total_pages=total_pages, current_page=page, prev_url=prev_url, next_url=next_url,
consignor=consignor, product_type=product_type, stock_manager=stock_manager, storage_location=storage_location, product_status=product_status, progress_status=progress_status)
# 재고 관리 페이지 라우트
@app.route('/stockManage', methods=['GET', 'POST'])
def stockManage():
if request.method == 'POST':
update_ids = request.form.getlist('update_id')
storage_location = request.form.get('storage_location', '')
progress_status = request.form.get('progress_status', '')
connection = create_connection()
cursor = connection.cursor()
for update_id in update_ids:
update_fields = []
update_values = []
if storage_location:
update_fields.append("storage_location = %s")
update_values.append(storage_location)
if progress_status:
update_fields.append("progress_status = %s")
update_values.append(progress_status)
update_values.append(update_id)
if update_fields:
cursor.execute(f"UPDATE stock SET {', '.join(update_fields)} WHERE id = %s", update_values)
connection.commit()
cursor.close()
connection.close()
return redirect(url_for('stockManage'))
page = request.args.get('page', 1, type=int)
per_page = 5
consignor = request.args.get('consignor', '')
product_type = request.args.get('product_type', '')
stock_manager = request.args.get('stock_manager', '')
storage_location = request.args.get('storage_location', '')
product_status = request.args.get('product_status', '')
progress_status = request.args.get('progress_status', '')
connection = create_connection()
cursor = connection.cursor(dictionary=True)
query = """
SELECT * FROM stock
WHERE consignor LIKE %s AND product_type LIKE %s AND stock_manager LIKE %s AND storage_location LIKE %s AND product_status LIKE %s AND progress_status LIKE %s
ORDER BY stock_update_date DESC
LIMIT %s OFFSET %s
"""
cursor.execute(query, ('%' + consignor + '%', '%' + product_type + '%', '%' + stock_manager + '%', '%' + storage_location + '%', '%' + product_status + '%', '%' + progress_status + '%', per_page, (page-1)*per_page))
results = cursor.fetchall()
cursor.execute("SELECT COUNT(*) FROM stock WHERE consignor LIKE %s AND product_type LIKE %s AND stock_manager LIKE %s AND storage_location LIKE %s AND product_status LIKE %s AND progress_status LIKE %s",
('%' + consignor + '%', '%' + product_type + '%', '%' + stock_manager + '%', '%' + storage_location + '%', '%' + product_status + '%', '%' + progress_status + '%'))
total = cursor.fetchone()['COUNT(*)']
total_pages = (total + per_page - 1) // per_page
cursor.close()
connection.close()
prev_url = url_for('stockManage', page=page-1, consignor=consignor, product_type=product_type, stock_manager=stock_manager, storage_location=storage_location, product_status=product_status, progress_status=progress_status) if page > 1 else None
next_url = url_for('stockManage', page=page+1, consignor=consignor, product_type=product_type, stock_manager=stock_manager, storage_location=storage_location, product_status=product_status, progress_status=progress_status) if page < total_pages else None
return render_template('stockManage.html', results=results, total_pages=total_pages, current_page=page, prev_url=prev_url, next_url=next_url,
consignor=consignor, product_type=product_type, stock_manager=stock_manager, storage_location=storage_location, product_status=product_status, progress_status=progress_status)
# 데이터 수정 및 삭제 라우트
@app.route('/save_changes', methods=['POST'])
def save_changes():
update_ids = request.form.getlist('update_id')
delete_ids = request.form.getlist('delete_id')
consignor = request.form.get('consignor', '')
product_type = request.form.get('product_type', '')
product_quantity = request.form.get('product_quantity', '')
arrival_date = request.form.get('arrival_date', '')
arrival_manager = request.form.get('arrival_manager', '')
storage_location = request.form.get('storage_location', '')
product_status = request.form.get('product_status', '')
progress_status = request.form.get('progress_status', '')
connection = create_connection()
cursor = connection.cursor()
for update_id in update_ids:
update_fields = []
update_values = []
if consignor:
update_fields.append("consignor = %s")
update_values.append(consignor)
if product_type:
update_fields.append("product_type = %s")
update_values.append(product_type)
if product_quantity:
update_fields.append("product_quantity = %s")
update_values.append(product_quantity)
if arrival_date:
update_fields.append("arrival_date = %s")
update_values.append(arrival_date)
if arrival_manager:
update_fields.append("arrival_manager = %s")
update_values.append(arrival_manager)
if storage_location:
update_fields.append("storage_location = %s")
update_values.append(storage_location)
if product_status:
update_fields.append("product_status = %s")
update_values.append(product_status)
if progress_status:
update_fields.append("progress_status = %s")
update_values.append(progress_status)
update_values.append(update_id)
if update_fields:
cursor.execute(f"UPDATE incoming SET {', '.join(update_fields)} WHERE id = %s", update_values)
for delete_id in delete_ids:
cursor.execute("DELETE FROM incoming WHERE id = %s", (delete_id,))
connection.commit()
cursor.close()
connection.close()
return redirect(url_for('enterView'))
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5001, debug=True)
오늘 WMS(Warehouse Management System) 기능 중 재고 조회 및 관리 기능을 구현해 봤다. 재고 조회, 관리 페이지를 제작해 보니 sql 언어가 더 어려워졌다. 예전에 다 배웠던 것인데 1도 기억이 안 난다... 다시 공부를 해야 될 것 같다. 그리고 "재고 수량의 update는 화주와 상품종류가 같을 때 입고 완료된 입고수량을 재고 수량에 더해서 저장" 하는 로직을 구현하는데 많이 시간을 할애 했는데 확실히 시간을 많이 할애해서 코드를 짜는 것이 코드를 이해하는데 좋은 것 같다. 아직 100%는 이해 못 했지만 flask 코드에 좀 더 익숙해지는 기회가 되었다.
'Python > Flask' 카테고리의 다른 글
[Day 9] WMS(Warehouse Management System) 구성 및 요구 사항 정의 4 (0) | 2024.07.25 |
---|---|
[Day 8] WMS(Warehouse Management System) 구성 및 요구 사항 정의 3 (4) | 2024.07.24 |
[Day 6] WMS(Warehouse Management System) 구성 및 요구 사항 정의 1 (2) | 2024.07.23 |
[Day 5] 사용자 인증 시스템 구현 (0) | 2024.07.21 |
[Day 4] Database 완성 (2) | 2024.07.18 |