{editingMaterial === material.id ? (
// Edit mode
@@ -488,15 +569,23 @@ const MaterialsList = ({ apiBaseUrl }) => {
) : (
// View mode
<>
- | {material.name} |
+
+ {material.name || material.product_name}
+ |
- {material.category || '-'}
+
+ {material.category || material.subcategory || '-'}
+
+ |
+
+ {material.unit || material.sales_unit || '-'}
|
- {material.unit} |
- {formatCurrency(material.unit_price)}
+ {formatCurrency(material.unit_price || material.price)}
+ |
+
+ {material.supplier_name || (material.source === 'bygma' ? 'Bygma' : '-')}
|
- {material.supplier_name || '-'} |
{material.description ?
(material.description.length > 40 ?
@@ -506,20 +595,29 @@ const MaterialsList = ({ apiBaseUrl }) => {
}
|
-
-
+ {material.source !== 'bygma' && (
+ <>
+
+
+ >
+ )}
+ {material.source === 'bygma' && (
+
+ 🏗️ Bygma
+
+ )}
|
>
)}
diff --git a/unified-server.js b/unified-server.js
index b01c48b..899bfd6 100644
--- a/unified-server.js
+++ b/unified-server.js
@@ -1980,28 +1980,85 @@ app.get('/api/real-project-types', async (req, res) => {
app.get('/api/pricing/materials', async (req, res) => {
try {
const category = req.query.category;
- let query = `
- SELECT
- mp.id,
- mp.name,
- mp.category,
- mp.unit,
- mp.price as unit_price,
- mp.supplier_name,
- mp.parse_log
- FROM material_prices mp
- WHERE mp.is_active = 1
- `;
- const params = [];
+ const search = req.query.search || '';
+ const limit = parseInt(req.query.limit) || 100;
+ const offset = parseInt(req.query.offset) || 0;
+ const includeBuiltIn = req.query.includeBuiltIn !== 'false'; // default true
+ const includeBygma = req.query.includeBygma !== 'false'; // default true
- if (category) {
- query += ' AND mp.category = ?';
- params.push(category);
+ let materials = [];
+
+ // Hent indbyggede materialer fra material_prices hvis ønsket
+ if (includeBuiltIn) {
+ let builtInQuery = `
+ SELECT
+ mp.id,
+ mp.name,
+ mp.category,
+ mp.unit,
+ mp.price as unit_price,
+ mp.supplier_name,
+ mp.parse_log,
+ 'built_in' as source,
+ 1 as is_active
+ FROM material_prices mp
+ WHERE mp.is_active = 1
+ `;
+ const builtInParams = [];
+
+ if (category) {
+ builtInQuery += ' AND mp.category = ?';
+ builtInParams.push(category);
+ }
+
+ if (search) {
+ builtInQuery += ' AND mp.name LIKE ?';
+ builtInParams.push(`%${search}%`);
+ }
+
+ const builtInMaterials = await databaseService.query(builtInQuery, builtInParams);
+ materials = materials.concat(builtInMaterials);
}
- query += ' ORDER BY mp.name';
+ // Hent Bygma materialer hvis ønsket
+ if (includeBygma) {
+ let bygmaQuery = `
+ SELECT
+ bp.id,
+ bp.tekst as name,
+ bp.varegrp as category,
+ bp.enhed as unit,
+ bp.current_netto_pris as unit_price,
+ 'Bygma' as supplier_name,
+ CONCAT('VareNr: ', bp.vareNr, ' | Gruppe: ', bp.varegrp) as parse_log,
+ 'bygma' as source,
+ bp.is_active,
+ bp.vareNr,
+ bp.current_brutto_pris,
+ bp.last_seen
+ FROM bygma_products bp
+ WHERE bp.is_active = 1
+ `;
+ const bygmaParams = [];
+
+ if (category) {
+ bygmaQuery += ' AND bp.varegrp = ?';
+ bygmaParams.push(category);
+ }
+
+ if (search) {
+ bygmaQuery += ' AND (bp.tekst LIKE ? OR bp.vareNr LIKE ?)';
+ bygmaParams.push(`%${search}%`, `%${search}%`);
+ }
+
+ bygmaQuery += ` ORDER BY bp.vareNr LIMIT ${limit} OFFSET ${offset}`;
+
+ const bygmaMaterials = await databaseService.query(bygmaQuery, bygmaParams);
+ materials = materials.concat(bygmaMaterials);
+ }
- const materials = await databaseService.query(query, params);
+ // Sortér samlet resultat
+ materials.sort((a, b) => a.name.localeCompare(b.name));
// Process materials to extract data from parse_log if needed
const processedMaterials = materials.map(material => {
@@ -2010,6 +2067,24 @@ app.get('/api/pricing/materials', async (req, res) => {
let unit = material.unit;
let description = '';
+ // Handle Bygma products differently
+ if (material.source === 'bygma') {
+ return {
+ id: material.id,
+ name: material.name || 'Ukendt Bygma produkt',
+ category: material.category || 'bygma',
+ unit: material.unit || 'stk',
+ unit_price: parseFloat(material.unit_price || 0),
+ brutto_price: parseFloat(material.current_brutto_pris || 0),
+ supplier_name: 'Bygma',
+ description: material.parse_log || '',
+ source: 'bygma',
+ vareNr: material.vareNr,
+ last_seen: material.last_seen
+ };
+ }
+
+ // Handle built-in materials
// If name is null, try to parse from parse_log
if (!name && material.parse_log) {
try {
@@ -2028,13 +2103,32 @@ app.get('/api/pricing/materials', async (req, res) => {
name: name || 'Ukendt materiale',
category: category || 'øvrige',
unit: unit || 'stk',
- unit_price: parseFloat(material.unit_price),
+ unit_price: parseFloat(material.unit_price || 0),
supplier_name: material.supplier_name || '',
- description: description
+ description: description,
+ source: 'built_in'
};
});
- res.json(processedMaterials);
+ // Hent også total count for pagination
+ const totalCountQuery = `
+ SELECT
+ (SELECT COUNT(*) FROM material_prices WHERE is_active = 1 ${category ? 'AND category = ?' : ''}) +
+ (SELECT COUNT(*) FROM bygma_products WHERE is_active = 1 ${category ? 'AND varegrp = ?' : ''}) as total
+ `;
+ const countParams = category ? [category, category] : [];
+ const [countResult] = await databaseService.query(totalCountQuery, countParams);
+
+ res.json({
+ success: true,
+ data: processedMaterials,
+ pagination: {
+ total: countResult.total,
+ limit: limit,
+ offset: offset,
+ hasMore: (offset + processedMaterials.length) < countResult.total
+ }
+ });
} catch (error) {
console.error('Error loading materials:', error);
res.status(500).json({ error: 'Fejl ved indlæsning af materialer' });
@@ -2184,7 +2278,7 @@ app.get('/api/pricing/bygma-products', async (req, res) => {
try {
const search = req.query.search || '';
const varegrp = req.query.varegrp || '';
- const limit = parseInt(req.query.limit) || 50;
+ const limit = parseInt(req.query.limit) || 100;
const offset = parseInt(req.query.offset) || 0;
let query = `
@@ -2197,6 +2291,7 @@ app.get('/api/pricing/bygma-products', async (req, res) => {
current_netto_pris,
current_brutto_pris,
last_seen,
+ is_active,
(SELECT COUNT(*) FROM bygma_materials_mapping WHERE bygma_product_id = bygma_products.id) as is_mapped
FROM bygma_products
WHERE is_active = 1