x
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from sqlalchemy import text
|
||||||
|
|
||||||
project_root = Path(__file__).parent.parent.parent
|
project_root = Path(__file__).parent.parent.parent
|
||||||
src_root = Path(__file__).parent.parent
|
src_root = Path(__file__).parent.parent
|
||||||
@@ -122,6 +123,7 @@ async def init_database():
|
|||||||
try:
|
try:
|
||||||
await db_manager.connect()
|
await db_manager.connect()
|
||||||
await db_manager.create_tables()
|
await db_manager.create_tables()
|
||||||
|
await ensure_schema_updates()
|
||||||
|
|
||||||
async with db_manager.session() as session:
|
async with db_manager.session() as session:
|
||||||
perm_map = await init_permissions(session)
|
perm_map = await init_permissions(session)
|
||||||
@@ -156,5 +158,30 @@ async def init_database():
|
|||||||
await db_manager.disconnect()
|
await db_manager.disconnect()
|
||||||
|
|
||||||
|
|
||||||
|
async def ensure_schema_updates():
|
||||||
|
async with db_manager.engine.begin() as conn:
|
||||||
|
await conn.execute(text("ALTER TABLE products ADD COLUMN IF NOT EXISTS item_type VARCHAR(20) DEFAULT 'finished'"))
|
||||||
|
await conn.execute(text("UPDATE products SET item_type = 'finished' WHERE item_type IS NULL"))
|
||||||
|
await conn.execute(text("ALTER TABLE sales_orders ADD COLUMN IF NOT EXISTS production_status VARCHAR(20) DEFAULT 'not_started'"))
|
||||||
|
await conn.execute(text("ALTER TABLE sales_orders ADD COLUMN IF NOT EXISTS production_no VARCHAR(50)"))
|
||||||
|
await conn.execute(text("ALTER TABLE sales_orders ADD COLUMN IF NOT EXISTS planned_material_cost DOUBLE PRECISION DEFAULT 0"))
|
||||||
|
await conn.execute(text("ALTER TABLE sales_orders ADD COLUMN IF NOT EXISTS actual_material_cost DOUBLE PRECISION DEFAULT 0"))
|
||||||
|
await conn.execute(text("""
|
||||||
|
CREATE TABLE IF NOT EXISTS product_materials (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
finished_product_id INTEGER NOT NULL REFERENCES products(id),
|
||||||
|
material_product_id INTEGER NOT NULL REFERENCES products(id),
|
||||||
|
quantity DOUBLE PRECISION NOT NULL,
|
||||||
|
loss_rate DOUBLE PRECISION DEFAULT 0,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP DEFAULT NOW()
|
||||||
|
)
|
||||||
|
"""))
|
||||||
|
await conn.execute(text("""
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_product_material_unique
|
||||||
|
ON product_materials (finished_product_id, material_product_id)
|
||||||
|
"""))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(init_database())
|
asyncio.run(init_database())
|
||||||
|
|||||||
+2
-2
@@ -1560,7 +1560,7 @@ const InventoryView = {
|
|||||||
const loadProducts = async () => {
|
const loadProducts = async () => {
|
||||||
state.loading = true;
|
state.loading = true;
|
||||||
try {
|
try {
|
||||||
state.products = await apiRequest('/api/products?limit=200');
|
state.products = await apiRequest('/api/products?limit=100');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleApiError(e, '加载产品');
|
handleApiError(e, '加载产品');
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1571,7 +1571,7 @@ const InventoryView = {
|
|||||||
const loadMaterials = async () => {
|
const loadMaterials = async () => {
|
||||||
state.loading = true;
|
state.loading = true;
|
||||||
try {
|
try {
|
||||||
state.materials = await apiRequest('/api/products?item_type=material&limit=300');
|
state.materials = await apiRequest('/api/products?item_type=material&limit=100');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleApiError(e, '加载物料');
|
handleApiError(e, '加载物料');
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user