#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <ctime>
using namespace std;
// -------------------- Utilities --------------------
static string todayDate() {
time_t t = time(nullptr);
tm *lt = localtime(&t);
ostringstream oss;
oss << (1900 + lt->tm_year) << '-'
<< setw(2) << setfill('0') << (1 + lt->tm_mon) << '-'
<< setw(2) << setfill('0') << lt->tm_mday;
return [Link]();
}
static bool isNumber(const string& s) {
if ([Link]()) return false;
for (char c : s) if (!isdigit(static_cast<unsigned char>(c))) return false;
return true;
}
// -------------------- Product (Base) --------------------
class Product {
protected:
int id{};
string name;
double unitPrice{};
int quantity{};
public:
Product() = default;
Product(int id, string name, double unitPrice, int quantity)
: id(id), name(std::move(name)), unitPrice(unitPrice), quantity(quantity) {}
virtual ~Product() = default;
int getId() const { return id; }
const string& getName() const { return name; }
int getQuantity() const { return quantity; }
void setName(const string& n) { name = n; }
void setUnitPrice(double p) { unitPrice = p; }
void setQuantity(int q) { quantity = q; }
// Runtime polymorphism: derived classes can change pricing behavior.
virtual double price() const { return unitPrice; }
// Used for saving/loading
virtual string typeTag() const { return "BASE"; }
// Serialize: TYPE|id|name|unitPrice|quantity|extra
virtual string serialize() const {
ostringstream oss;
oss << typeTag() << "|" << id << "|" << name << "|"
<< fixed << setprecision(2) << unitPrice << "|" << quantity << "|";
return [Link]();
}
static Product* deserialize(const string& line); // factory
friend ostream& operator<<(ostream& os, const Product& p) {
os << left << setw(6) << [Link]
<< left << setw(22) << [Link](0, 21)
<< right << setw(10) << fixed << setprecision(2) << [Link]()
<< right << setw(10) << [Link]
<< " " << [Link]();
return os;
}
};
// -------------------- Product (Derived) --------------------
class DiscountedProduct : public Product {
double discountPercent{}; // e.g., 10 means 10%
public:
DiscountedProduct() = default;
DiscountedProduct(int id, string name, double unitPrice, int quantity, double
discountPercent)
: Product(id, std::move(name), unitPrice, quantity), discountPercent(discountPercent) {}
double price() const override {
double d = max(0.0, min(100.0, discountPercent));
return unitPrice * (1.0 - d / 100.0);
}
string typeTag() const override { return "DISC"; }
double getDiscountPercent() const { return discountPercent; }
void setDiscountPercent(double d) { discountPercent = d; }
string serialize() const override {
ostringstream oss;
oss << typeTag() << "|" << id << "|" << name << "|"
<< fixed << setprecision(2) << unitPrice << "|" << quantity << "|"
<< fixed << setprecision(2) << discountPercent;
return [Link]();
}
};
// Factory method
Product* Product::deserialize(const string& line) {
// TYPE|id|name|unitPrice|quantity|extra
vector<string> parts;
{
string token;
istringstream iss(line);
while (getline(iss, token, '|')) parts.push_back(token);
}
if ([Link]() < 5) return nullptr;
string type = parts[0];
int id = stoi(parts[1]);
string name = parts[2];
double unitPrice = stod(parts[3]);
int qty = stoi(parts[4]);
if (type == "DISC") {
double disc = 0.0;
if ([Link]() >= 6 && !parts[5].empty()) disc = stod(parts[5]);
return new DiscountedProduct(id, name, unitPrice, qty, disc);
}
return new Product(id, name, unitPrice, qty);
}
// -------------------- Sales Record --------------------
struct Sale {
string date; // YYYY-MM-DD
int productId{};
string productName;
int units{};
double unitSoldPrice{};
double total{};
string serialize() const {
ostringstream oss;
oss << date << "|" << productId << "|" << productName << "|"
<< units << "|" << fixed << setprecision(2) << unitSoldPrice << "|"
<< fixed << setprecision(2) << total;
return [Link]();
}
static bool deserialize(const string& line, Sale& s) {
vector<string> parts;
string token;
istringstream iss(line);
while (getline(iss, token, '|')) parts.push_back(token);
if ([Link]() != 6) return false;
[Link] = parts[0];
[Link] = stoi(parts[1]);
[Link] = parts[2];
[Link] = stoi(parts[3]);
[Link] = stod(parts[4]);
[Link] = stod(parts[5]);
return true;
}
};
// -------------------- Inventory System --------------------
class InventorySystem {
vector<Product*> products;
const string productsFile = "[Link]";
const string salesFile = "[Link]";
public:
InventorySystem() { loadProducts(); }
~InventorySystem() { clearProducts(); }
// --------- Polymorphism (Overloading) ---------
void addProduct(Product* p) {
if (!p) return;
if (findProductById(p->getId()) != nullptr) {
cout << "Error: Product ID already exists.\n";
delete p;
return;
}
products.push_back(p);
saveProducts();
cout << "Product added.\n";
}
void addProduct(int id, const string& name, double price, int qty) {
addProduct(new Product(id, name, price, qty));
}
void addProduct(int id, const string& name, double price, int qty, double discountPercent) {
addProduct(new DiscountedProduct(id, name, price, qty, discountPercent));
}
// --------- CRUD ---------
void listProducts() const {
if ([Link]()) {
cout << "No products found.\n";
return;
}
cout << "\nID NAME PRICE QTY TYPE\n";
cout << "----------------------------------------------------------\n";
for (const auto* p : products) cout << *p << "\n";
}
void createProduct() {
int id, qty;
double price;
string name;
cout << "Enter ID (number): ";
cin >> id;
[Link](numeric_limits<streamsize>::max(), '\n');
cout << "Enter Name: ";
getline(cin, name);
cout << "Enter Unit Price: ";
cin >> price;
cout << "Enter Quantity: ";
cin >> qty;
cout << "Is it discounted? (y/n): ";
char ch;
cin >> ch;
if (ch == 'y' || ch == 'Y') {
double disc;
cout << "Enter discount percent (0-100): ";
cin >> disc;
addProduct(id, name, price, qty, disc);
} else {
addProduct(id, name, price, qty);
}
}
void updateProduct() {
int id;
cout << "Enter product ID to update: ";
cin >> id;
Product* p = findProductById(id);
if (!p) {
cout << "Product not found.\n";
return;
}
[Link](numeric_limits<streamsize>::max(), '\n');
string name;
cout << "New name (leave blank to keep): ";
getline(cin, name);
if (![Link]()) p->setName(name);
string tmp;
cout << "New unit price (leave blank to keep): ";
getline(cin, tmp);
if (![Link]()) p->setUnitPrice(stod(tmp));
cout << "New quantity (leave blank to keep): ";
getline(cin, tmp);
if (![Link]()) p->setQuantity(stoi(tmp));
// If it's DiscountedProduct, allow updating discount
if (auto* dp = dynamic_cast<DiscountedProduct*>(p)) {
cout << "New discount percent (leave blank to keep): ";
getline(cin, tmp);
if (![Link]()) dp->setDiscountPercent(stod(tmp));
}
saveProducts();
cout << "Product updated.\n";
}
void deleteProduct() {
int id;
cout << "Enter product ID to delete: ";
cin >> id;
auto it = remove_if([Link](), [Link](),
[&](Product* p) { return p && p->getId() == id; });
if (it == [Link]()) {
cout << "Product not found.\n";
return;
}
for (auto iter = it; iter != [Link](); ++iter) delete *iter;
[Link](it, [Link]());
saveProducts();
cout << "Product deleted.\n";
}
// --------- Sales ---------
void sellProduct() {
int id, units;
cout << "Enter product ID to sell: ";
cin >> id;
Product* p = findProductById(id);
if (!p) {
cout << "Product not found.\n";
return;
}
cout << "Enter units to sell: ";
cin >> units;
if (units <= 0) {
cout << "Invalid units.\n";
return;
}
if (p->getQuantity() < units) {
cout << "Not enough stock.\n";
return;
}
double soldPrice = p->price(); // runtime polymorphism here
double total = soldPrice * units;
// reduce stock
p->setQuantity(p->getQuantity() - units);
saveProducts();
// record sale
Sale s;
[Link] = todayDate();
[Link] = p->getId();
[Link] = p->getName();
[Link] = units;
[Link] = soldPrice;
[Link] = total;
appendSale(s);
cout << "Sale recorded. Total: " << fixed << setprecision(2) << total << "\n";
}
void generateSalesReport() const {
vector<Sale> sales = loadSales();
if ([Link]()) {
cout << "No sales found.\n";
return;
}
double grandTotal = 0.0;
cout << "\nDATE ID NAME UNITS UNIT TOTAL\n";
cout << "-----------------------------------------------------------------------\n";
for (const auto& s : sales) {
grandTotal += [Link];
cout << left << setw(12) << [Link]
<< left << setw(7) << [Link]
<< left << setw(25) << [Link](0, 24)
<< right << setw(6) << [Link]
<< right << setw(9) << fixed << setprecision(2) << [Link]
<< right << setw(10) << fixed << setprecision(2) << [Link]
<< "\n";
}
cout << "-----------------------------------------------------------------------\n";
cout << "GRAND TOTAL SALES: " << fixed << setprecision(2) << grandTotal << "\n";
}
// --------- Menu ---------
void menu() {
while (true) {
cout << "\n===== INVENTORY MANAGEMENT SYSTEM =====\n"
<< "1. Create Product\n"
<< "2. View Products\n"
<< "3. Update Product\n"
<< "4. Delete Product\n"
<< "5. Sell Product (Generate Sales)\n"
<< "6. Sales Report\n"
<< "0. Exit\n"
<< "Choose: ";
int choice;
cin >> choice;
switch (choice) {
case 1: createProduct(); break;
case 2: listProducts(); break;
case 3: updateProduct(); break;
case 4: deleteProduct(); break;
case 5: sellProduct(); break;
case 6: generateSalesReport(); break;
case 0: cout << "Exiting...\n"; return;
default: cout << "Invalid choice.\n"; break;
}
}
}
private:
void clearProducts() {
for (auto* p : products) delete p;
[Link]();
}
Product* findProductById(int id) {
for (auto* p : products) if (p && p->getId() == id) return p;
return nullptr;
}
void loadProducts() {
clearProducts();
ifstream in(productsFile);
if (!in) return; // first run is fine
string line;
while (getline(in, line)) {
if ([Link]()) continue;
Product* p = Product::deserialize(line);
if (p) products.push_back(p);
}
}
void saveProducts() const {
ofstream out(productsFile, ios::trunc);
for (const auto* p : products) {
if (p) out << p->serialize() << "\n";
}
}
void appendSale(const Sale& s) const {
ofstream out(salesFile, ios::app);
out << [Link]() << "\n";
}
vector<Sale> loadSales() const {
vector<Sale> sales;
ifstream in(salesFile);
if (!in) return sales;
string line;
while (getline(in, line)) {
if ([Link]()) continue;
Sale s;
if (Sale::deserialize(line, s)) sales.push_back(s);
}
return sales;
}
};
// -------------------- Main --------------------
int main() {
ios::sync_with_stdio(false);
[Link](nullptr);
InventorySystem system;
[Link]();
return 0;
}