Kgshop commited on
Commit
fe6c35c
·
verified ·
1 Parent(s): 1402eb4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +7 -14
app.py CHANGED
@@ -79,7 +79,7 @@ def load_json_data(file_key):
79
  with open(filepath, 'r', encoding='utf-8') as f:
80
  return json.load(f)
81
  except (FileNotFoundError, json.JSONDecodeError):
82
- return [] if file_key != 'users' else {}
83
 
84
  def save_json_data(file_key, data):
85
  filepath, lock = DATA_FILES[file_key]
@@ -374,7 +374,6 @@ def stock_in():
374
  for i, variant in enumerate(product.get('variants', [])):
375
  if variant.get('id') == variant_id:
376
  variant['stock'] = variant.get('stock', 0) + quantity
377
- # Update cost price if provided, using weighted average
378
  if cost_price_str:
379
  new_cost = to_decimal(cost_price_str)
380
  old_stock = variant.get('stock', 0) - quantity
@@ -406,7 +405,6 @@ def get_product_by_barcode(barcode):
406
  inventory = load_json_data('inventory')
407
  product = find_item_by_field(inventory, 'barcode', barcode)
408
  if product:
409
- # Return only variants that are in stock
410
  active_variants = [v for v in product.get('variants', []) if v.get('stock', 0) > 0]
411
  if active_variants:
412
  product_copy = product.copy()
@@ -656,7 +654,7 @@ def product_roi_report():
656
  if t['type'] == 'sale':
657
  total_qty_sold += item['quantity']
658
  elif t['type'] == 'return':
659
- total_qty_sold += item['quantity'] # quantity is negative on returns
660
 
661
  current_stock = to_decimal(str(variant.get('stock', 0)))
662
  cost_price = to_decimal(variant.get('cost_price', '0'))
@@ -1006,7 +1004,10 @@ BASE_TEMPLATE = """
1006
  .main-content { margin-left: 0; }
1007
  }
1008
  [data-bs-theme="dark"] body { background-color: #212529; color: #dee2e6; }
1009
- [data-bs-theme="dark"] .card, [data-bs-theme="dark"] .modal-content, [data-bs-theme="dark"] .list-group-item, [data-bs-theme="dark"] .table { background-color: #343a40; }
 
 
 
1010
  [data-bs-theme="dark"] .table-hover>tbody>tr:hover>* { color: var(--bs-table-hover-color); background-color: rgba(255, 255, 255, 0.075); }
1011
  .product-card { cursor: pointer; }
1012
  .product-card:hover { border-color: var(--bs-primary); }
@@ -1321,7 +1322,7 @@ document.addEventListener('DOMContentLoaded', () => {
1321
  document.querySelectorAll('.product-card').forEach(card => {
1322
  const productName = card.querySelector('.card-title').textContent.toLowerCase();
1323
  const show = productName.includes(term) || card.dataset.barcode.includes(term);
1324
- card.parentElement.style.display = show ? '' : 'none'; // Target parent if inside a grid wrapper
1325
  });
1326
  });
1327
 
@@ -1458,7 +1459,6 @@ INVENTORY_CONTENT = """
1458
  {% endfor %}
1459
  </div>
1460
 
1461
- <!-- Add Product Modal -->
1462
  <div class="modal fade" id="addProductModal" tabindex="-1">
1463
  <div class="modal-dialog modal-lg">
1464
  <div class="modal-content">
@@ -1475,7 +1475,6 @@ INVENTORY_CONTENT = """
1475
  <hr>
1476
  <h6>Варианты товара</h6>
1477
  <div id="variants-container-add">
1478
- <!-- Variant fields will be added here by JS -->
1479
  </div>
1480
  <button type="button" class="btn btn-sm btn-outline-success mt-2" id="add-variant-btn-add">Добавить вариант</button>
1481
  </div>
@@ -1485,7 +1484,6 @@ INVENTORY_CONTENT = """
1485
  </div>
1486
  </div>
1487
 
1488
- <!-- Edit Product Modals -->
1489
  {% for p in inventory %}
1490
  <div class="modal fade" id="editProductModal-{{ p.id }}" tabindex="-1">
1491
  <div class="modal-dialog modal-lg">
@@ -1520,7 +1518,6 @@ INVENTORY_CONTENT = """
1520
  </div>
1521
  {% endfor %}
1522
 
1523
- <!-- Stock In Modal -->
1524
  <div class="modal fade" id="stockInModal" tabindex="-1">
1525
  <div class="modal-dialog">
1526
  <div class="modal-content">
@@ -1563,7 +1560,6 @@ INVENTORY_CONTENT = """
1563
  INVENTORY_SCRIPTS = """
1564
  <script>
1565
  document.addEventListener('DOMContentLoaded', () => {
1566
- // --- Barcode Scanner Logic for Modals ---
1567
  let currentScanner = null;
1568
  let currentScannerContainer = null;
1569
  document.querySelectorAll('.scan-modal-btn').forEach(btn => {
@@ -1608,7 +1604,6 @@ document.addEventListener('DOMContentLoaded', () => {
1608
  });
1609
  });
1610
 
1611
- // --- Dynamic Variant Fields Logic ---
1612
  const createVariantRow = () => {
1613
  const div = document.createElement('div');
1614
  div.className = 'row g-2 mb-2 align-items-center variant-row';
@@ -1639,7 +1634,6 @@ document.addEventListener('DOMContentLoaded', () => {
1639
  btn.addEventListener('click', e => e.target.closest('.variant-row').remove());
1640
  });
1641
 
1642
- // Auto-add first variant row on add modal show
1643
  const addProductModal = document.getElementById('addProductModal');
1644
  addProductModal.addEventListener('shown.bs.modal', () => {
1645
  const container = document.getElementById('variants-container-add');
@@ -1648,7 +1642,6 @@ document.addEventListener('DOMContentLoaded', () => {
1648
  }
1649
  });
1650
 
1651
- // --- Stock In Modal Logic ---
1652
  const inventoryData = JSON.parse('{{ inventory|tojson|safe }}');
1653
  const productSelect = document.getElementById('stockin-product');
1654
  const variantSelect = document.getElementById('stockin-variant');
 
79
  with open(filepath, 'r', encoding='utf-8') as f:
80
  return json.load(f)
81
  except (FileNotFoundError, json.JSONDecodeError):
82
+ return []
83
 
84
  def save_json_data(file_key, data):
85
  filepath, lock = DATA_FILES[file_key]
 
374
  for i, variant in enumerate(product.get('variants', [])):
375
  if variant.get('id') == variant_id:
376
  variant['stock'] = variant.get('stock', 0) + quantity
 
377
  if cost_price_str:
378
  new_cost = to_decimal(cost_price_str)
379
  old_stock = variant.get('stock', 0) - quantity
 
405
  inventory = load_json_data('inventory')
406
  product = find_item_by_field(inventory, 'barcode', barcode)
407
  if product:
 
408
  active_variants = [v for v in product.get('variants', []) if v.get('stock', 0) > 0]
409
  if active_variants:
410
  product_copy = product.copy()
 
654
  if t['type'] == 'sale':
655
  total_qty_sold += item['quantity']
656
  elif t['type'] == 'return':
657
+ total_qty_sold += item['quantity']
658
 
659
  current_stock = to_decimal(str(variant.get('stock', 0)))
660
  cost_price = to_decimal(variant.get('cost_price', '0'))
 
1004
  .main-content { margin-left: 0; }
1005
  }
1006
  [data-bs-theme="dark"] body { background-color: #212529; color: #dee2e6; }
1007
+ [data-bs-theme="dark"] .card, [data-bs-theme="dark"] .modal-content, [data-bs-theme="dark"] .list-group-item, [data-bs-theme="dark"] .table, [data-bs-theme="dark"] .accordion-item { background-color: #343a40; }
1008
+ [data-bs-theme="dark"] .accordion-button { background-color: #3e444a; color: #fff; }
1009
+ [data-bs-theme="dark"] .accordion-button:not(.collapsed) { background-color: #495057;}
1010
+ [data-bs-theme="dark"] .accordion-button::after { filter: invert(1) grayscale(100) brightness(200%); }
1011
  [data-bs-theme="dark"] .table-hover>tbody>tr:hover>* { color: var(--bs-table-hover-color); background-color: rgba(255, 255, 255, 0.075); }
1012
  .product-card { cursor: pointer; }
1013
  .product-card:hover { border-color: var(--bs-primary); }
 
1322
  document.querySelectorAll('.product-card').forEach(card => {
1323
  const productName = card.querySelector('.card-title').textContent.toLowerCase();
1324
  const show = productName.includes(term) || card.dataset.barcode.includes(term);
1325
+ card.style.display = show ? '' : 'none';
1326
  });
1327
  });
1328
 
 
1459
  {% endfor %}
1460
  </div>
1461
 
 
1462
  <div class="modal fade" id="addProductModal" tabindex="-1">
1463
  <div class="modal-dialog modal-lg">
1464
  <div class="modal-content">
 
1475
  <hr>
1476
  <h6>Варианты товара</h6>
1477
  <div id="variants-container-add">
 
1478
  </div>
1479
  <button type="button" class="btn btn-sm btn-outline-success mt-2" id="add-variant-btn-add">Добавить вариант</button>
1480
  </div>
 
1484
  </div>
1485
  </div>
1486
 
 
1487
  {% for p in inventory %}
1488
  <div class="modal fade" id="editProductModal-{{ p.id }}" tabindex="-1">
1489
  <div class="modal-dialog modal-lg">
 
1518
  </div>
1519
  {% endfor %}
1520
 
 
1521
  <div class="modal fade" id="stockInModal" tabindex="-1">
1522
  <div class="modal-dialog">
1523
  <div class="modal-content">
 
1560
  INVENTORY_SCRIPTS = """
1561
  <script>
1562
  document.addEventListener('DOMContentLoaded', () => {
 
1563
  let currentScanner = null;
1564
  let currentScannerContainer = null;
1565
  document.querySelectorAll('.scan-modal-btn').forEach(btn => {
 
1604
  });
1605
  });
1606
 
 
1607
  const createVariantRow = () => {
1608
  const div = document.createElement('div');
1609
  div.className = 'row g-2 mb-2 align-items-center variant-row';
 
1634
  btn.addEventListener('click', e => e.target.closest('.variant-row').remove());
1635
  });
1636
 
 
1637
  const addProductModal = document.getElementById('addProductModal');
1638
  addProductModal.addEventListener('shown.bs.modal', () => {
1639
  const container = document.getElementById('variants-container-add');
 
1642
  }
1643
  });
1644
 
 
1645
  const inventoryData = JSON.parse('{{ inventory|tojson|safe }}');
1646
  const productSelect = document.getElementById('stockin-product');
1647
  const variantSelect = document.getElementById('stockin-variant');