1st publish
commit
813171deba
@ -0,0 +1,9 @@
|
|||||||
|
**/__pycache__/
|
||||||
|
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
*.log
|
||||||
|
|
||||||
|
*.idea
|
||||||
|
|
||||||
|
myenv/
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
import logging
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
|
||||||
|
# 确保日志目录存在
|
||||||
|
log_dir = 'logs'
|
||||||
|
os.makedirs(log_dir, exist_ok=True)
|
||||||
|
|
||||||
|
# 配置日志
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||||
|
handlers=[
|
||||||
|
logging.FileHandler(f'{log_dir}/app.log'),
|
||||||
|
logging.StreamHandler()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
while True:
|
||||||
|
logger.info("Hello World from Docker Compose!")
|
||||||
|
time.sleep(5)
|
||||||
@ -0,0 +1,98 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import locale
|
||||||
|
import mysql.connector
|
||||||
|
from mysql.connector import Error
|
||||||
|
|
||||||
|
# 强制系统使用UTF-8
|
||||||
|
sys.stdout.reconfigure(encoding='utf-8')
|
||||||
|
sys.stderr.reconfigure(encoding='utf-8')
|
||||||
|
locale.setlocale(locale.LC_ALL, 'C.UTF-8')
|
||||||
|
|
||||||
|
if sys.platform != 'win32':
|
||||||
|
os.environ['TZ'] = 'Asia/Shanghai'
|
||||||
|
time.tzset() # 重新加载时区配置
|
||||||
|
|
||||||
|
# 确保日志目录存在
|
||||||
|
log_dir = 'logs'
|
||||||
|
os.makedirs(log_dir, exist_ok=True)
|
||||||
|
|
||||||
|
# 配置日志
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||||
|
handlers=[
|
||||||
|
logging.FileHandler(f'{log_dir}/app.log', encoding='utf-8'),
|
||||||
|
logging.StreamHandler()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
class CSTFormatter(logging.Formatter):
|
||||||
|
def formatTime(self, record, datefmt=None):
|
||||||
|
ct = datetime.fromtimestamp(record.created).astimezone()
|
||||||
|
if datefmt:
|
||||||
|
s = ct.strftime(datefmt)
|
||||||
|
else:
|
||||||
|
t = ct.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
s = "%s,%03d" % (t, record.msecs)
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def get_table_count(db_name):
|
||||||
|
try:
|
||||||
|
# 连接到MySQL数据库
|
||||||
|
connection = mysql.connector.connect(
|
||||||
|
host='106.227.91.181',
|
||||||
|
user='root', # 替换为您的MySQL用户名
|
||||||
|
password='cuixing@HuaerdaMySQL', # 替换为您的MySQL密码
|
||||||
|
database='huaerdames_cloud'
|
||||||
|
# host= 'localhost',
|
||||||
|
# user='root', # 替换为您的MySQL用户名
|
||||||
|
# password='root', # 替换为您的MySQL密码
|
||||||
|
# database='huaerdames_cloud'
|
||||||
|
)
|
||||||
|
|
||||||
|
if connection.is_connected():
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
# 获取所有表名
|
||||||
|
cursor.execute(f"SHOW TABLES FROM {db_name}")
|
||||||
|
tables = cursor.fetchall()
|
||||||
|
|
||||||
|
# 统计每个表的记录数
|
||||||
|
table_counts = {}
|
||||||
|
for table in tables:
|
||||||
|
table_name = table[0]
|
||||||
|
cursor.execute(f"SELECT COUNT(*) FROM {table_name}")
|
||||||
|
count = cursor.fetchone()[0]
|
||||||
|
table_counts[table_name] = count
|
||||||
|
|
||||||
|
return table_counts
|
||||||
|
|
||||||
|
except Error as e:
|
||||||
|
logger.error(f"数据库连接错误: {e}")
|
||||||
|
return None
|
||||||
|
finally:
|
||||||
|
if connection.is_connected():
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# 统计表数量
|
||||||
|
db_name = 'huaerdames_cloud'
|
||||||
|
table_counts = get_table_count(db_name)
|
||||||
|
|
||||||
|
if table_counts:
|
||||||
|
logger.info(f"数据库 '{db_name}' 表统计:")
|
||||||
|
for table, count in table_counts.items():
|
||||||
|
logger.info(f"表名: {table}, 记录数: {count}")
|
||||||
|
logger.info(f"总表数: {len(table_counts)}")
|
||||||
|
else:
|
||||||
|
logger.warning("未能获取表统计信息")
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
DB_CONFIG = {
|
||||||
|
"user": "root",
|
||||||
|
"password": "cuixing@HuaerdaMySQL",
|
||||||
|
"host": "106.227.91.181",
|
||||||
|
"port": 3306,
|
||||||
|
"database": "huaerdames_cloud"
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
version: '3.11'
|
||||||
|
|
||||||
|
services:
|
||||||
|
python-logger:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
# 启用 BuildKit 缓存
|
||||||
|
args:
|
||||||
|
- BUILDKIT_INLINE_CACHE=1 # 允许缓存复用
|
||||||
|
container_name: my-python-logger
|
||||||
|
volumes:
|
||||||
|
- ./logs:/app/logs
|
||||||
|
working_dir: /app
|
||||||
|
#restart: unless-stopped
|
||||||
|
restart: on-failure
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
from sqlalchemy import Column, BigInteger, String, DECIMAL, DateTime, Boolean
|
||||||
|
|
||||||
|
Base = declarative_base()
|
||||||
|
|
||||||
|
class WmsIngredientsLog(Base):
|
||||||
|
__tablename__ = 'wms_ingredients_log'
|
||||||
|
|
||||||
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
||||||
|
net_weight = Column(DECIMAL(24,2))
|
||||||
|
is_deleted = Column(Boolean, default=False)
|
||||||
|
create_time = Column(DateTime)
|
||||||
|
# 其他字段省略...
|
||||||
|
code_sn = Column(String(50))
|
||||||
|
ingredients_id = Column(BigInteger)
|
||||||
|
ingredients_name = Column(String(90))
|
||||||
|
manufacturer_id = Column(BigInteger)
|
||||||
|
manufacturer_name = Column(String(90))
|
||||||
|
part_number = Column(String(50))
|
||||||
|
lot_number = Column(String(50))
|
||||||
|
product_id = Column(BigInteger)
|
||||||
|
product_name = Column(String(90))
|
||||||
|
item_specification = Column(String(90))
|
||||||
|
item_id = Column(BigInteger)
|
||||||
|
net_weight = Column(DECIMAL(24,2))
|
||||||
|
gross_weight = Column(DECIMAL(24,2))
|
||||||
|
tare_weight = Column(DECIMAL(24,2), default=0.00)
|
||||||
|
measure_id = Column(BigInteger)
|
||||||
|
measure_name = Column(String(90))
|
||||||
|
job_number = Column(String(90))
|
||||||
|
status = Column(String(1))
|
||||||
|
is_deleted = Column(Boolean, default=False)
|
||||||
|
version = Column(BigInteger, default=0)
|
||||||
|
create_by = Column(String(100))
|
||||||
|
create_time = Column(DateTime)
|
||||||
|
update_by = Column(String(100))
|
||||||
|
update_time = Column(DateTime)
|
||||||
|
attr1 = Column(String(255))
|
||||||
|
attr2 = Column(BigInteger)
|
||||||
|
# attr3 JSON 可加 sqlalchemy.dialects.mysql.JSON
|
||||||
|
order_weight = Column(DECIMAL(24,2))
|
||||||
|
is_documents = Column(String(1))
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
@ -0,0 +1,15 @@
|
|||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from service.wms_ingredients_service import WmsIngredientsService
|
||||||
|
|
||||||
|
service = WmsIngredientsService()
|
||||||
|
df = service.get_monthly_weight_df()
|
||||||
|
|
||||||
|
plt.figure(figsize=(12, 6))
|
||||||
|
plt.plot(df["month"], df["total_weight"], marker="o")
|
||||||
|
plt.title("Monthly Net Weight Statistics")
|
||||||
|
plt.xlabel("Month")
|
||||||
|
plt.ylabel("Total Net Weight")
|
||||||
|
plt.grid(True)
|
||||||
|
plt.xticks(rotation=45)
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
from config.database import SessionLocal
|
||||||
|
from sqlalchemy import text
|
||||||
|
|
||||||
|
class BaseRepository:
|
||||||
|
def __init__(self):
|
||||||
|
self.session = SessionLocal()
|
||||||
|
|
||||||
|
def add(self, obj):
|
||||||
|
self.session.add(obj)
|
||||||
|
self.session.commit()
|
||||||
|
self.session.refresh(obj)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def delete(self, obj):
|
||||||
|
self.session.delete(obj)
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
|
def get_by_id(self, entity, id_):
|
||||||
|
return self.session.query(entity).get(id_)
|
||||||
|
|
||||||
|
def list_all(self, entity):
|
||||||
|
return self.session.query(entity).all()
|
||||||
|
|
||||||
|
def execute_sql(self, sql, params=None):
|
||||||
|
"""执行原生 SQL"""
|
||||||
|
result = self.session.execute(text(sql), params or {})
|
||||||
|
return result.fetchall()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.session.close()
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
from repository.base_repository import BaseRepository
|
||||||
|
from entity.wms_ingredients_log import WmsIngredientsLog
|
||||||
|
|
||||||
|
class WmsIngredientsLogRepository(BaseRepository):
|
||||||
|
def get_monthly_net_weight(self):
|
||||||
|
sql = """
|
||||||
|
SELECT DATE_FORMAT(create_time, '%Y-%m') AS month,
|
||||||
|
SUM(net_weight) AS total_weight
|
||||||
|
FROM wms_ingredients_log
|
||||||
|
WHERE is_deleted = 0
|
||||||
|
AND net_weight IS NOT NULL
|
||||||
|
AND create_time IS NOT NULL
|
||||||
|
GROUP BY DATE_FORMAT(create_time, '%Y-%m')
|
||||||
|
ORDER BY month
|
||||||
|
"""
|
||||||
|
return self.execute_sql(sql)
|
||||||
|
def get_ingredients_log_by_code_sn(self, code_sn: str):
|
||||||
|
sql = """
|
||||||
|
SELECT *
|
||||||
|
FROM wms_ingredients_log
|
||||||
|
WHERE code_sn = :code_sn
|
||||||
|
AND is_deleted = 0
|
||||||
|
LIMIT 1
|
||||||
|
"""
|
||||||
|
rows = self.execute_sql(sql, {"code_sn": code_sn})
|
||||||
|
return rows[0] if rows else None
|
||||||
Binary file not shown.
@ -0,0 +1,14 @@
|
|||||||
|
import pandas as pd
|
||||||
|
from repository.wms_ingredients_log_repository import WmsIngredientsLogRepository
|
||||||
|
|
||||||
|
class WmsIngredientsService:
|
||||||
|
def __init__(self):
|
||||||
|
self.repo = WmsIngredientsLogRepository()
|
||||||
|
|
||||||
|
def get_monthly_weight_df(self):
|
||||||
|
rows = self.repo.get_monthly_net_weight()
|
||||||
|
df = pd.DataFrame(rows, columns=["month", "total_weight"])
|
||||||
|
df["month"] = pd.to_datetime(df["month"])
|
||||||
|
return df
|
||||||
|
def get_ingredients_log_by_code_sn(self, code_sn: str):
|
||||||
|
return self.repo.get_ingredients_log_by_code_sn(code_sn)
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
from service.wms_ingredients_service import WmsIngredientsService
|
||||||
|
|
||||||
|
service = WmsIngredientsService()
|
||||||
|
|
||||||
|
record = service.get_ingredients_log_by_code_sn("ITEM_2508290093006")
|
||||||
|
print(record)
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import mysql.connector
|
||||||
|
import pandas as pd
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
# Database connection
|
||||||
|
try:
|
||||||
|
cloud_conn = mysql.connector.connect(
|
||||||
|
host='106.227.91.181',
|
||||||
|
database='huaerdames_cloud',
|
||||||
|
port=3306,
|
||||||
|
user='root',
|
||||||
|
password='cuixing@HuaerdaMySQL'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Query to get net_weight by month
|
||||||
|
query = """
|
||||||
|
SELECT
|
||||||
|
DATE_FORMAT(create_time, '%Y-%m') as month,
|
||||||
|
SUM(net_weight) as total_weight
|
||||||
|
FROM wms_ingredients_log
|
||||||
|
WHERE is_deleted = 0
|
||||||
|
AND net_weight IS NOT NULL
|
||||||
|
AND create_time IS NOT NULL
|
||||||
|
GROUP BY DATE_FORMAT(create_time, '%Y-%m')
|
||||||
|
ORDER BY month
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Execute query and load data into DataFrame
|
||||||
|
df = pd.read_sql(query, cloud_conn)
|
||||||
|
|
||||||
|
# Close database connection
|
||||||
|
cloud_conn.close()
|
||||||
|
|
||||||
|
# Convert month to datetime for better plotting
|
||||||
|
df['month'] = pd.to_datetime(df['month'])
|
||||||
|
|
||||||
|
# Create the plot
|
||||||
|
plt.figure(figsize=(12, 6))
|
||||||
|
plt.plot(df['month'], df['total_weight'], marker='o')
|
||||||
|
|
||||||
|
# Customize the plot
|
||||||
|
plt.title('Monthly Net Weight Statistics', fontsize=14)
|
||||||
|
plt.xlabel('Month', fontsize=12)
|
||||||
|
plt.ylabel('Total Net Weight', fontsize=12)
|
||||||
|
plt.grid(True)
|
||||||
|
|
||||||
|
# Rotate x-axis labels for better readability
|
||||||
|
plt.xticks(rotation=45)
|
||||||
|
|
||||||
|
# Adjust layout to prevent label cutoff
|
||||||
|
plt.tight_layout()
|
||||||
|
|
||||||
|
# Save the plot
|
||||||
|
plt.savefig('monthly_weight_plot.png')
|
||||||
|
|
||||||
|
# Show the plot
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
except mysql.connector.Error as err:
|
||||||
|
print(f"Database error: {err}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
Loading…
Reference in New Issue