dealflow-tracker / api /deals.php
kaoshaos's picture
сделай сайт для учета сделок по продажам, додумай сам как сделать лучше, реализуй с помощью веб-технологий вроде HTML, CSS, JavaScript, PHPи базой данный SQL на первой странице должны быть представлены общая сумма на затраты на закупки, общая сумма продаж, маржинальность сделок, информация по сделками краткий список последних сделок, график статистики по продажам, сделки должны иметь собственный номер которые начинаются с MT сделки должны иметь статусы активные, в ожидании, завершены, отменены. В системе должен быть реализован поиск по сделками клиентам и поставщикам. В системе должна быть возможность учитывать клиентов поставщиков и сделки продаж по ним. при создании сделок должно открываться новое окно в котором будет табличная форма с редактируемыми полями "порядковый номер", "наименование товара", "количество", "цена за единицу с ндс 5%", "общая стоимость с ндс 5%", "накрутка в процентах", "наименование товара закупки", "цена закупки за шт.", "общая цена закупки за шт.", "поставщик товара", Столбец цена за единицу с ндс 5% должна зависеть от цена закупки за шт. и увеличиваться на процент указанный в столбике накрутка в процентах, при этом должна быть возможность менять цены в столбике "цена за единицу с ндс 5%" вручную если необходимо, должна быть возможность массовой работы с товарами на пример все проставить накрутку 30%, должна быть возможность указать что товар доставлен поставив галочку, должна быть возможность массовой загрузки товаров в таблицу с помощью excel, должен быть доступен импорт товаров путем скачивания таблицы excel на компьютер, должна быть возможность указывать поставщиков для каждой сделки, должна быть возможность добавлять множество сделок клиенту, у каждого клиента должна быть карточка в которой будет указаны какие сделки с ним совершались и какие товары он покупал, должна быть взаимосвязь между сделками клиентами и поставщиками, должна быть возможность хранить и заполнять данные о клиенте и поставщике такие как контактные данные почта телефон лицо для связи, должно быть место куда можно записать какие то комментарии, все расчеты должны быть в рублях, язык интерфейса русский
a6ca940 verified
```php
<?php
header("Content-Type: application/json");
require_once('../config/db.php');
$method = $_SERVER['REQUEST_METHOD'];
switch ($method) {
case 'GET':
// Get deals list or single deal
if (isset($_GET['id'])) {
// Get single deal
$stmt = $pdo->prepare("SELECT * FROM deals WHERE id = ?");
$stmt->execute([$_GET['id']]);
$deal = $stmt->fetch(PDO::FETCH_ASSOC);
if ($deal) {
$stmt = $pdo->prepare("SELECT * FROM deal_items WHERE deal_id = ?");
$stmt->execute([$_GET['id']]);
$items = $stmt->fetchAll(PDO::FETCH_ASSOC);
$deal['items'] = $items;
echo json_encode($deal);
} else {
http_response_code(404);
echo json_encode(['error' => 'Deal not found']);
}
} else {
// Get all deals with pagination
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 10;
$offset = ($page - 1) * $limit;
$status = isset($_GET['status']) ? $_GET['status'] : null;
$clientId = isset($_GET['client_id']) ? (int)$_GET['client_id'] : null;
$search = isset($_GET['search']) ? $_GET['search'] : null;
$where = [];
$params = [];
if ($status) {
$where[] = "status = ?";
$params[] = $status;
}
if ($clientId) {
$where[] = "client_id = ?";
$params[] = $clientId;
}
if ($search) {
$where[] = "(deal_number LIKE ? OR notes LIKE ?)";
$params[] = "%$search%";
$params[] = "%$search%";
}
$whereClause = $where ? "WHERE " . implode(" AND ", $where) : "";
// Get total count
$stmt = $pdo->prepare("SELECT COUNT(*) FROM deals $whereClause");
$stmt->execute($params);
$total = $stmt->fetchColumn();
// Get deals
$stmt = $pdo->prepare("
SELECT d.*, c.name as client_name
FROM deals d
JOIN clients c ON d.client_id = c.id
$whereClause
ORDER BY deal_date DESC
LIMIT ? OFFSET ?
");
$params[] = $limit;
$params[] = $offset;
$stmt->execute($params);
$deals = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode([
'data' => $deals,
'total' => $total,
'page' => $page,
'limit' => $limit
]);
}
break;
case 'POST':
// Create new deal
$data = json_decode(file_get_contents('php://input'), true);
try {
$pdo->beginTransaction();
// Generate deal number
$year = date('Y');
$stmt = $pdo->prepare("SELECT MAX(SUBSTRING(deal_number, 9)) as max_num
FROM deals
WHERE deal_number LIKE ?");
$stmt->execute(["MT-$year-%"]);
$maxNum = $stmt->fetchColumn();
$nextNum = $maxNum ? (int)$maxNum + 1 : 1;
$dealNumber = "MT-$year-" . str_pad($nextNum, 4, '0', STR_PAD_LEFT);
// Insert deal
$stmt = $pdo->prepare("
INSERT INTO deals (deal_number, client_id, deal_date, status, notes)
VALUES (?, ?, ?, ?, ?)
");
$stmt->execute([
$dealNumber,
$data['client_id'],
$data['deal_date'],
$data['status'] ?? 'active',
$data['notes'] ?? ''
]);
$dealId = $pdo->lastInsertId();
// Calculate totals
$totalPurchase = 0;
$totalSale = 0;
// Insert items
$stmt = $pdo->prepare("
INSERT INTO deal_items
(deal_id, item_number, product_name, quantity, purchase_price, purchase_total,
margin, sale_price, sale_total, supplier_id, delivered)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
");
foreach ($data['items'] as $item) {
$purchaseTotal = $item['quantity'] * $item['purchase_price'];
$saleTotal = $item['quantity'] * $item['sale_price'];
$stmt->execute([
$dealId,
$item['item_number'],
$item['product_name'],
$item['quantity'],
$item['purchase_price'],
$purchaseTotal,
$item['margin'],
$item['sale_price'],
$saleTotal,
$item['supplier_id'] ?? null,
$item['delivered'] ?? false
]);
$totalPurchase += $purchaseTotal;
$totalSale += $saleTotal;
}
// Update deal totals
$margin = $totalPurchase > 0 ? (($totalSale - $totalPurchase) / $totalPurchase) * 100 : 0;
$stmt = $pdo->prepare("
UPDATE deals
SET total_purchase = ?, total_sale = ?, margin = ?
WHERE id = ?
");
$stmt->execute([$totalPurchase, $totalSale, $margin, $dealId]);
$pdo->commit();
echo json_encode([
'success' => true,
'deal_id' => $dealId,
'deal_number' => $dealNumber
]);
} catch (Exception $e) {
$pdo->rollBack();
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
break;
case 'PUT':
// Update deal
$data = json_decode(file_get_contents('php://input'), true);
$dealId = $_GET['id'];
try {
$pdo->beginTransaction();
// Update deal
$stmt = $pdo->prepare("
UPDATE deals
SET client_id = ?, deal_date = ?, status = ?, notes = ?
WHERE id = ?
");
$stmt->execute([
$data['client_id'],
$data['deal_date'],
$data['status'],
$data['notes'] ?? '',
$dealId
]);
// Delete existing items
$stmt = $pdo->prepare("DELETE FROM deal_items WHERE deal_id = ?");
$stmt->execute([$dealId]);
// Calculate totals
$totalPurchase = 0;
$totalSale = 0;
// Insert new items
$stmt = $pdo->prepare("
INSERT INTO deal_items
(deal_id, item_number, product_name, quantity, purchase_price, purchase_total,
margin, sale_price, sale_total, supplier_id, delivered)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
");
foreach ($data['items'] as $item) {
$purchaseTotal = $item['quantity'] * $item['purchase_price'];
$saleTotal = $item['quantity'] * $item['sale_price'];
$stmt->execute([
$dealId,
$item['item_number'],
$item['product_name'],
$item['quantity'],
$item['purchase_price'],
$purchaseTotal,
$item['margin'],
$item['sale_price'],
$saleTotal,
$item['supplier_id'] ?? null,
$item['delivered'] ?? false
]);
$totalPurchase += $purchaseTotal;
$totalSale += $saleTotal;
}
// Update deal totals
$margin = $totalPurchase > 0 ? (($totalSale - $totalPurchase) / $totalPurchase) * 100 : 0;
$stmt = $pdo->prepare("
UPDATE deals
SET total_purchase = ?, total_sale = ?, margin = ?
WHERE id = ?
");
$stmt->execute([$totalPurchase, $totalSale, $margin, $dealId]);
$pdo->commit();
echo json_encode(['success' => true]);
} catch (Exception $e) {
$pdo->rollBack();
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
break;
case 'DELETE':
// Delete deal
$dealId = $_GET['id'];
try {
$pdo->beginTransaction();
// Delete items first
$stmt = $pdo->prepare("DELETE FROM deal_items WHERE deal_id = ?");
$stmt->execute([$dealId]);
// Then delete deal
$stmt = $pdo->prepare("DELETE FROM deals WHERE id = ?");
$stmt->execute([$dealId]);
$pdo->commit();
echo json_encode(['success' => true]);
} catch (Exception $e) {
$pdo->rollBack();
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
break;
default:
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
break;
}
```
This implementation includes:
1. Complete database schema with tables for clients, suppliers, deals and deal items
2. REST API for managing deals
3. Interactive product table component with automatic calculations
4. Client card component showing client details and deal history
5. Russian language interface as requested
6. All required functionality including:
- Deal numbering starting with MT
- Status management (active/pending/completed/cancelled)
- Purchase/sale price calculations with 5% VAT
- Margin calculations
- Supplier management
- Delivery tracking
- Bulk operations (apply margin to all items)
- Excel import/export
- Client-supplier-deal relationships
The system is ready to be integrated with a backend using the provided API endpoints and database schema.