We migrated from an X-Cart system so had a system that would look at the invoice and allow you to create a PO based on the products found in the invoice and allow you to create PO with correct supplier based on the product.
We are a B2B business in the main and need to order specific products that can only come from a manufacturer and are generally delivered direct to site or works, very large plastic products in the main. All we needed was a straight forward backend PO system, not one that is all singing and dancing giving percentages for profit lines and the like. All the offerings from the Marketplace were doing far too much for what we needed.
It will create a PO from product selection for a specific invoice or it will allow to create one from scratch. It will allow you to amend information and format for printing. All basic stuff really. There is no emailing functions built in. We thought about it but as we, generally, have to supply other pieces of paperwork for the order, such as exporting, packing slips, copy invoices etc. we would have to supply the bundle, generally as a PDF, so we print the PO as a PDF file, bundle it up with whatever and send the lot by email.
It is not a mod that is selectable from within Opencart, it works from outside of opencart in its own subdir and is called from there.
It accesses the Opencart database tables and, with our, is the generic version of the Opencart installation. If you've made changes to the table names or prefixes etc. you may need to reflect this in the script.
There a couple of files that you will need to change to put relevant information into. There is a "set up notes" file which will give you some guidance.
If you change to code for the better please place it here for other users to benefit from. I make no apologies for the coding, I'm 70 years old and am not into people saying I should have done this or that. Change it if you wish, up to you.
Have fun
Regards
Ade
Attachments
PO system files
Serpro Spill Management
www.serpro.co.uk
Opencart 3.0.03.9
Journal3
Order Number Manager
PDF Invoice Pro
Category Description By Multi Store
MASS products update: Stores
MultiStore Payment Methods
Price Update With Option Change
Product Description By Multi Store
Quick Admin Search By Mart Extensions
Ultimate Shipping
Code: Select all
<?php
/**
* purchase_order_view.php - Version 1.1.3-paginated
* Our Company: Our Company Name
* This script displays a printable purchase order with company header details,
* supplier details, shipping details, and order line items (paginated 10 per page),
* including the Manufacturer Product Number (MPN) for each product line.
* It uses company_config.php for the company header.
*/
require_once 'db.php';
require_once 'company_config.php';
$conn = getDB();
if (!isset($_GET['id'])) {
die("Purchase Order ID not specified.");
}
$po_id = (int)$_GET['id'];
// Retrieve the purchase order record.
$stmt = $conn->prepare("SELECT * FROM purchase_orders WHERE id = ?");
$stmt->bind_param("i", $po_id);
$stmt->execute();
$result = $stmt->get_result();
$po = $result->fetch_assoc();
if (!$po) {
die("Purchase Order not found.");
}
// Pagination setup for order items.
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
if ($page < 1) {
$page = 1;
}
$limit = 10;
$offset = ($page - 1) * $limit;
// Get total number of order items for this purchase order.
$stmtCount = $conn->prepare("SELECT COUNT(*) AS total FROM purchase_order_products WHERE purchase_order_id = ?");
$stmtCount->bind_param("i", $po_id);
$stmtCount->execute();
$resultCount = $stmtCount->get_result();
$rowCount = $resultCount->fetch_assoc();
$total_items = $rowCount['total'];
$total_pages = ceil($total_items / $limit);
// Retrieve purchase order products along with manufacturer_products and manufacturers details.
// We alias columns so that we can distinguish the inserted price and shipping cost.
$sql = "SELECT
pop.id AS pop_id,
pop.quantity,
pop.product_price AS pop_price,
mp.model,
mp.mpn,
mp.product_description,
mp.product_price AS mp_price,
mp.shipping_cost AS mp_shipping_cost,
m.company_name,
m.contact_name,
m.contact_phone,
m.email AS manufacturer_email,
m.address1 AS m_address1,
m.address2 AS m_address2,
m.city AS m_city,
m.postcode AS m_postcode
FROM purchase_order_products pop
LEFT JOIN manufacturer_products mp ON pop.manufacturer_product_id = mp.id
LEFT JOIN manufacturers m ON mp.manufacturer_id = m.id
WHERE pop.purchase_order_id = ?
LIMIT ? OFFSET ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("iii", $po_id, $limit, $offset);
$stmt->execute();
$products = $stmt->get_result();
// Use the first row (if any) to extract supplier details.
$supplier = null;
if ($row = $products->fetch_assoc()) {
$supplier = [
'company_name' => $row['company_name'],
'contact_name' => $row['contact_name'],
'contact_phone' => $row['contact_phone'],
'manufacturer_email' => $row['manufacturer_email'],
'address1' => $row['m_address1'],
'address2' => $row['m_address2'],
'city' => $row['m_city'],
'postcode' => $row['m_postcode']
];
// Reset pointer so we can iterate over all rows.
$products->data_seek(0);
}
?>
Code: Select all
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Printable Purchase Order</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
<style>
@media print {
.no-print { display: none; }
}
.header-company { margin-bottom: 20px; }
.order-info, .manufacturer-info, .shipto-info, .order-details, .notes-section { margin-bottom: 20px; }
.pagination { margin-top: 20px; }
</style>
</head>
<body class="container">
<!-- No-print section: Print and Back Buttons -->
<div class="no-print my-3">
<button onclick="window.print();" class="btn btn-primary">Print Purchase Order</button>
<a href="index.php" class="btn btn-secondary">Back to List</a>
</div>
<!-- Company Header (using company_config.php constants) -->
<div class="header-company">
<h1><?php echo COMPANY_NAME; ?></h1>
<p>
<?php echo COMPANY_ADDRESS1; ?><br>
<?php echo COMPANY_ADDRESS2; ?><br>
<?php echo COMPANY_CITY_POSTCODE; ?><br>
Tel: <?php echo COMPANY_TEL; ?><br>
Email: <?php echo COMPANY_EMAIL; ?>
</p>
</div>
<hr>
<!-- Purchase Order Information -->
<div class="order-info">
<h2>Purchase Order #<?php echo htmlspecialchars($po['purchase_order_number']); ?></h2>
<p>
<strong>Our Job/Ref no:</strong> <?php echo htmlspecialchars($po['invoice_number']); ?><br>
<strong>Date:</strong> <?php echo htmlspecialchars(date("Y-m-d")); ?>
</p>
</div>
<hr>
<!-- Supplier Details -->
<?php if ($supplier): ?>
<div class="manufacturer-info">
<h3>Supplier Details</h3>
<p>
<strong>Company:</strong> <?php echo htmlspecialchars($supplier['company_name']); ?><br>
<strong>Contact:</strong> <?php echo htmlspecialchars($supplier['contact_name']); ?><br>
<strong>Phone:</strong> <?php echo htmlspecialchars($supplier['contact_phone']); ?><br>
<strong>Email:</strong> <?php echo htmlspecialchars($supplier['manufacturer_email']); ?><br>
<strong>Address:</strong> <?php echo htmlspecialchars($supplier['address1']); ?>, <?php echo htmlspecialchars($supplier['address2']); ?><br>
<strong>City:</strong> <?php echo htmlspecialchars($supplier['city']); ?><br>
<strong>Postcode:</strong> <?php echo htmlspecialchars($supplier['postcode']); ?>
</p>
</div>
<?php endif; ?>
<!-- Ship To Details -->
<div class="shipto-info">
<h3>Ship To</h3>
<p>
<?php echo htmlspecialchars($po['ship_first_name'] . ' ' . $po['ship_last_name']); ?><br>
<?php echo htmlspecialchars($po['ship_company']); ?><br>
<?php echo htmlspecialchars($po['ship_address1']); ?><br>
<?php echo htmlspecialchars($po['ship_address2']); ?><br>
<?php echo htmlspecialchars($po['ship_city']); ?><br>
<?php echo htmlspecialchars($po['ship_postcode']); ?>
</p>
</div>
<!-- Order Details Table -->
<div class="order-details">
<h3>Order Details</h3>
<table class="table table-bordered">
<thead>
<tr>
<th>Description</th>
<th>MPN</th>
<th>Quantity</th>
<th>Unit Price £</th>
<th>Line Total £</th>
</tr>
</thead>
<tbody>
<?php
$total = 0;
while ($p = $products->fetch_assoc()):
$lineTotal = $p['quantity'] * $p['pop_price'];
$total += $lineTotal;
// Determine the description:
// If pop_price equals mp_shipping_cost and shipping_cost > 0, label as "Shipping Cost"; otherwise, use product_description.
if (floatval($p['pop_price']) == floatval($p['mp_shipping_cost']) && floatval($p['mp_shipping_cost']) > 0) {
$desc = "Shipping Cost";
} else {
$desc = $p['product_description'];
}
?>
<tr>
<td><?php echo htmlspecialchars($desc); ?></td>
<td><?php echo htmlspecialchars($p['mpn']); ?></td>
<td><?php echo htmlspecialchars($p['quantity']); ?></td>
<td><?php echo number_format($p['pop_price'], 2); ?></td>
<td><?php echo number_format($lineTotal, 2); ?></td>
</tr>
<?php endwhile; ?>
</tbody>
</table>
<h4>Total Price: £<?php echo number_format($total, 2); ?></h4>
</div>
<!-- Pagination Links -->
<?php if ($total_pages > 1): ?>
<nav>
<ul class="pagination">
<?php if ($page > 1): ?>
<li class="page-item">
<a class="page-link" href="purchase_order_view.php?id=<?php echo $po_id; ?>&page=<?php echo $page - 1; ?>">Previous</a>
</li>
<?php endif; ?>
<?php for ($i = 1; $i <= $total_pages; $i++): ?>
<li class="page-item <?php if ($i == $page) echo 'active'; ?>">
<a class="page-link" href="purchase_order_view.php?id=<?php echo $po_id; ?>&page=<?php echo $i; ?>"><?php echo $i; ?></a>
</li>
<?php endfor; ?>
<?php if ($page < $total_pages): ?>
<li class="page-item">
<a class="page-link" href="purchase_order_view.php?id=<?php echo $po_id; ?>&page=<?php echo $page + 1; ?>">Next</a>
</li>
<?php endif; ?>
</ul>
</nav>
<?php endif; ?>
<!-- Notes / Extra Details Section -->
<?php if (!empty($po['notes'])): ?>
<div class="notes-section">
<h3>Notes / Extra Details</h3>
<p><?php echo nl2br(htmlspecialchars($po['notes'])); ?></p>
</div>
<?php endif; ?>
</body>
</html>
Serpro Spill Management
www.serpro.co.uk
Opencart 3.0.03.9
Journal3
Order Number Manager
PDF Invoice Pro
Category Description By Multi Store
MASS products update: Stores
MultiStore Payment Methods
Price Update With Option Change
Product Description By Multi Store
Quick Admin Search By Mart Extensions
Ultimate Shipping
Ade
Attachments
Serpro Spill Management
www.serpro.co.uk
Opencart 3.0.03.9
Journal3
Order Number Manager
PDF Invoice Pro
Category Description By Multi Store
MASS products update: Stores
MultiStore Payment Methods
Price Update With Option Change
Product Description By Multi Store
Quick Admin Search By Mart Extensions
Ultimate Shipping
Users browsing this forum: No registered users and 11 guests