Untitled

 avatar
unknown
plain_text
a month ago
13 kB
3
Indexable
#include <iostream>
#include <map>
#include <locale.h>
#include <vector>
#include <sqlite3.h>  // Добавляем заголовок SQLite

using namespace std;

// Класс для работы с базой данных
class Database {
private:
    sqlite3* db;
    
    void execute(const string& query) {
        char* errMsg;
        if(sqlite3_exec(db, query.c_str(), nullptr, nullptr, &errMsg) != SQLITE_OK) {
            cerr << "Ошибка SQL: " << errMsg << endl;
            sqlite3_free(errMsg);
        }
    }

public:
    Database() {
        if(sqlite3_open("materials.db", &db) != SQLITE_OK) {
            cerr << "Ошибка открытия БД: " << sqlite3_errmsg(db) << endl;
            exit(1);
        }
        
        // Создаем таблицы
        execute(
            "CREATE TABLE IF NOT EXISTS Materials ("
            "id INTEGER PRIMARY KEY AUTOINCREMENT,"
            "name TEXT NOT NULL UNIQUE,"
            "quantity INTEGER NOT NULL);"
            
            "CREATE TABLE IF NOT EXISTS Products ("
            "id INTEGER PRIMARY KEY AUTOINCREMENT,"
            "name TEXT NOT NULL UNIQUE);"
            
            "CREATE TABLE IF NOT EXISTS ProductMaterials ("
            "product_id INTEGER NOT NULL,"
            "material_id INTEGER NOT NULL,"
            "quantity INTEGER NOT NULL,"
            "FOREIGN KEY(product_id) REFERENCES Products(id),"
            "FOREIGN KEY(material_id) REFERENCES Materials(id));"
        );
    }

    ~Database() {
        sqlite3_close(db);
    }

    sqlite3* handle() { return db; }
};

// Класс для управления складом
class Inventory {
private:
    Database& db;

public:
    Inventory(Database& database) : db(database) {}

    void addMaterial(const string& name, int quantity) {
        sqlite3_stmt* stmt;
        const char* query = 
            "INSERT INTO Materials (name, quantity) "
            "VALUES (?, COALESCE((SELECT quantity FROM Materials WHERE name = ?), 0) + ?)";
        
        sqlite3_prepare_v2(db.handle(), query, -1, &stmt, nullptr);
        sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_STATIC);
        sqlite3_bind_text(stmt, 2, name.c_str(), -1, SQLITE_STATIC);
        sqlite3_bind_int(stmt, 3, quantity);
        
        sqlite3_step(stmt);
        sqlite3_finalize(stmt);
        cout << "Добавлено " << quantity << " ед. " << name << " на склад.\n";
    }

    bool removeMaterial(const string& name, int quantity) {
        sqlite3_stmt* stmt;
        bool success = false;
        const char* query = 
            "UPDATE Materials SET quantity = quantity - ? "
            "WHERE name = ? AND quantity >= ?";
        
        sqlite3_prepare_v2(db.handle(), query, -1, &stmt, nullptr);
        sqlite3_bind_int(stmt, 1, quantity);
        sqlite3_bind_text(stmt, 2, name.c_str(), -1, SQLITE_STATIC);
        sqlite3_bind_int(stmt, 3, quantity);
        
        if(sqlite3_step(stmt) == SQLITE_DONE) {
            if(sqlite3_changes(db.handle()) > 0) {
                cout << "Списано " << quantity << " ед. " << name << " со склада.\n";
                success = true;
            } else {
                cout << "Ошибка: недостаточно " << name << " на складе.\n";
            }
        }
        
        sqlite3_finalize(stmt);
        return success;
    }

    void showInventory() {
        sqlite3_stmt* stmt;
        cout << "\n--- Склад ---\n";
        const char* query = "SELECT name, quantity FROM Materials";
        
        sqlite3_prepare_v2(db.handle(), query, -1, &stmt, nullptr);
        
        while(sqlite3_step(stmt) == SQLITE_ROW) {
            cout << sqlite3_column_text(stmt, 0) << ": "
                 << sqlite3_column_int(stmt, 1) << " ед.\n";
        }
        cout << "--------------\n";
        sqlite3_finalize(stmt);
    }

    bool hasMaterial(const string& name, int quantity) {
        sqlite3_stmt* stmt;
        bool result = false;
        const char* query = "SELECT quantity FROM Materials WHERE name = ?";
        
        sqlite3_prepare_v2(db.handle(), query, -1, &stmt, nullptr);
        sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_STATIC);
        
        if(sqlite3_step(stmt) == SQLITE_ROW) {
            result = (sqlite3_column_int(stmt, 0) >= quantity);
        }
        
        sqlite3_finalize(stmt);
        return result;
    }
};

// Класс для каталога продукции
class ProductCatalog {
private:
    Database& db;

    int getMaterialId(const string& name) {
        sqlite3_stmt* stmt;
        int id = -1;
        const char* query = "SELECT id FROM Materials WHERE name = ?";
        
        sqlite3_prepare_v2(db.handle(), query, -1, &stmt, nullptr);
        sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_STATIC);
        
        if(sqlite3_step(stmt) == SQLITE_ROW) {
            id = sqlite3_column_int(stmt, 0);
        }
        
        sqlite3_finalize(stmt);
        return id;
    }

public:
    ProductCatalog(Database& database) : db(database) {}

    void addProduct(const string& productName, const map<string, int>& materials) {
        sqlite3_stmt* stmt;
        const char* query = "INSERT INTO Products (name) VALUES (?)";
        
        sqlite3_prepare_v2(db.handle(), query, -1, &stmt, nullptr);
        sqlite3_bind_text(stmt, 1, productName.c_str(), -1, SQLITE_STATIC);
        sqlite3_step(stmt);
        int productId = sqlite3_last_insert_rowid(db.handle());
        sqlite3_finalize(stmt);

        for(const auto& [matName, qty] : materials) {
            int matId = getMaterialId(matName);
            if(matId == -1) {
                cerr << "Материал " << matName << " не найден!\n";
                continue;
            }

            const char* insertQuery = 
                "INSERT INTO ProductMaterials (product_id, material_id, quantity) "
                "VALUES (?, ?, ?)";
            
            sqlite3_prepare_v2(db.handle(), insertQuery, -1, &stmt, nullptr);
            sqlite3_bind_int(stmt, 1, productId);
            sqlite3_bind_int(stmt, 2, matId);
            sqlite3_bind_int(stmt, 3, qty);
            
            sqlite3_step(stmt);
            sqlite3_finalize(stmt);
        }
        cout << "Продукт " << productName << " добавлен в каталог.\n";
    }

    void showProducts() {
        sqlite3_stmt* stmt;
        cout << "\n--- Каталог продукции ---\n";
        const char* query = 
            "SELECT p.name, m.name, pm.quantity "
            "FROM Products p "
            "JOIN ProductMaterials pm ON p.id = pm.product_id "
            "JOIN Materials m ON pm.material_id = m.id";
        
        sqlite3_prepare_v2(db.handle(), query, -1, &stmt, nullptr);
        
        map<string, vector<pair<string, int>>> products;
        while(sqlite3_step(stmt) == SQLITE_ROW) {
            string productName = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
            string matName = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
            int quantity = sqlite3_column_int(stmt, 2);
            products[productName].emplace_back(matName, quantity);
        }

        for(const auto& [name, materials] : products) {
            cout << name << " (нужно: ";
            for(const auto& [mat, qty] : materials) {
                cout << mat << " - " << qty << " ед., ";
            }
            cout << ")\n";
        }
        cout << "-------------------------\n";
        sqlite3_finalize(stmt);
    }

    map<string, int> getProductMaterials(const string& productName) {
        sqlite3_stmt* stmt;
        map<string, int> materials;
        const char* query = 
            "SELECT m.name, pm.quantity "
            "FROM Products p "
            "JOIN ProductMaterials pm ON p.id = pm.product_id "
            "JOIN Materials m ON pm.material_id = m.id "
            "WHERE p.name = ?";
        
        sqlite3_prepare_v2(db.handle(), query, -1, &stmt, nullptr);
        sqlite3_bind_text(stmt, 1, productName.c_str(), -1, SQLITE_STATIC);
        
        while(sqlite3_step(stmt) == SQLITE_ROW) {
            string matName = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
            int quantity = sqlite3_column_int(stmt, 1);
            materials[matName] = quantity;
        }
        
        sqlite3_finalize(stmt);
        return materials;
    }

    bool hasProduct(const string& productName) {
        sqlite3_stmt* stmt;
        bool exists = false;
        const char* query = "SELECT 1 FROM Products WHERE name = ?";
        
        sqlite3_prepare_v2(db.handle(), query, -1, &stmt, nullptr);
        sqlite3_bind_text(stmt, 1, productName.c_str(), -1, SQLITE_STATIC);
        exists = (sqlite3_step(stmt) == SQLITE_ROW);
        
        sqlite3_finalize(stmt);
        return exists;
    }
};

// Основной класс системы
class MaterialAccountingSystem {
private:
    Database db;
    Inventory inventory;
    ProductCatalog catalog;

public:
    MaterialAccountingSystem() : db(), inventory(db), catalog(db) {}

    void addMaterialToInventory() {
        string name;
        int quantity;
        cout << "Введите название материала: ";
        cin >> name;
        cout << "Введите количество: ";
        cin >> quantity;
        inventory.addMaterial(name, quantity);
    }

    void addProductToCatalog() {
        string productName;
        cout << "Введите название продукта: ";
        cin >> productName;

        map<string, int> materials;
        while(true) {
            string materialName;
            int materialQuantity;

            cout << "Введите название материала (или 'gotovo' для завершения): ";
            cin >> materialName;

            if(materialName == "gotovo") break;

            cout << "Введите необходимое количество: ";
            cin >> materialQuantity;

            materials[materialName] = materialQuantity;
        }

        if(materials.empty()) {
            cout << "Ошибка: не добавлено ни одного материала! Продукт не сохранён.\n";
        } else {
            catalog.addProduct(productName, materials);
        }
    }

    void produceProduct() {
        string productName;
        cout << "Введите название продукта для производства: ";
        cin >> productName;

        if(!catalog.hasProduct(productName)) {
            cout << "Ошибка: продукт не найден в каталоге!\n";
            return;
        }

        map<string, int> requiredMaterials = catalog.getProductMaterials(productName);
        for(const auto& [mat, qty] : requiredMaterials) {
            if(!inventory.hasMaterial(mat, qty)) {
                cout << "Ошибка: недостаточно материала " << mat << "!\n";
                return;
            }
        }

        for(const auto& [mat, qty] : requiredMaterials) {
            inventory.removeMaterial(mat, qty);
        }

        cout << "Продукт " << productName << " успешно произведён!\n";
    }

    void showInventory() {
        inventory.showInventory();
    }

    void showProductCatalog() {
        catalog.showProducts();
    }

    void menu() {
        while(true) {
            cout << "\nВыберите действие:\n"
                 << "1. Добавить материал на склад\n"
                 << "2. Добавить новый продукт\n"
                 << "3. Показать склад\n"
                 << "4. Показать каталог\n"
                 << "5. Произвести продукт\n"
                 << "6. Выйти\n"
                 << "Ваш выбор: ";

            int choice;
            cin >> choice;

            switch(choice) {
                case 1: addMaterialToInventory(); break;
                case 2: addProductToCatalog(); break;
                case 3: showInventory(); break;
                case 4: showProductCatalog(); break;
                case 5: produceProduct(); break;
                case 6: return;
                default: cout << "Неверный выбор!\n";
            }
        }
    }
};

int main() {
    setlocale(LC_ALL, "RUS");
    MaterialAccountingSystem system;
    system.menu();
    return 0;
}
Editor is loading...
Leave a Comment