Am Frontend besiedelt der Select2 die Felder nicht, damit der Benutzer auswählen kannJavaScript

Javascript-Forum
Guest
 Am Frontend besiedelt der Select2 die Felder nicht, damit der Benutzer auswählen kann

Post by Guest »

Ich habe eine Rechnung, um das Datum für die PostgreSQL -Datenbank zu sammeln, und ich habe Probleme, mit Endpunkten ordnungsgemäß zu arbeiten und die Dropdown -Liste für das Feld des Verkaufsnamens und des Produktnamens zu bevölkern. JSON -Antwort und es liefert das Frontend mit Sätzen, während mit meinem anderen Backend -Code die JSON -Antworten gültig waren, die Select2 konnte nicht ausgefüllt werden und dann den geteilten Namen im Feld beibehalten. < /p>
Frontend < /p>

Code: Select all

// Initialize Select2 components
$(document).ready(function() {
$('#salesman').select2({
placeholder: 'Select Salesman',
ajax: {
url: '/api/salesmen',
dataType: 'json',
delay: 250,
processResults: data => ({
results: data
})
}
});
initProductSelect($('.product-row').first().find('.product-name'));
});

function initProductSelect(element) {
element.select2({
placeholder: 'Select Product',
ajax: {
url: '/api/products',
dataType: 'json',
delay: 250,
processResults: data => ({
results: data
})
}
}).on('select2:select', async function(e) {
const row = $(this).closest('.product-row');
try {
const response = await fetch(`/api/product/${e.params.data.id}`);
const product = await response.json();
row.data('conversion', product.conversion_rate)
.find('.stock-ctn, .added-ctn, .return-ctn').attr('placeholder', product.primary_unit)
.closest('tr').find('.total-dispatch-ctn, .sold-ctn').text(`0 ${product.primary_unit}`);
} catch (error) {
console.error('Error loading product:', error);
}
});
}

function convertToPieces(ctn, pcs, row) {
return (ctn * row.data('conversion')) + (parseInt(pcs) || 0);
}

function updateTotalDispatch(row) {
const $row = $(row);
const conversion = $row.data('conversion') || 1;
const stockCtn = parseInt($row.find('.stock-ctn').val()) || 0;
const stockPcs = parseInt($row.find('.stock-pcs').val()) || 0;
const addedCtn = parseInt($row.find('.added-ctn').val()) || 0;
const addedPcs = parseInt($row.find('.added-pcs').val()) || 0;
const totalPieces = (stockCtn + addedCtn) * conversion + stockPcs + addedPcs;

$row.find('.total-dispatch-ctn').text(`${Math.floor(totalPieces/conversion)} ${$row.find('.stock-ctn').attr('placeholder')}`);
$row.find('.total-dispatch-pcs').text(`${totalPieces % conversion} Pcs`);
}

function updateSoldStock(row) {
const $row = $(row);
const conversion = $row.data('conversion') || 1;

// Parse inputs with fallback to 0 if empty or invalid
const stockCtn = parseInt($row.find('.stock-ctn').val()) || 0;
const stockPcs = parseInt($row.find('.stock-pcs').val()) || 0;
const addedCtn = parseInt($row.find('.added-ctn').val()) || 0;
const addedPcs = parseInt($row.find('.added-pcs').val()) || 0;
const returnCtn = parseInt($row.find('.return-ctn').val()) || 0;
const returnPcs = parseInt($row.find('.return-pcs').val()) || 0;

// Calculate total stock and return
const totalStock = (stockCtn + addedCtn) * conversion + (stockPcs + addedPcs);
const totalReturn = returnCtn * conversion + returnPcs;

// Validate return doesn't exceed stock
if (totalReturn >  totalStock) {
const maxReturn = totalStock;
$row.find('.return-ctn').val(Math.floor(maxReturn / conversion));
$row.find('.return-pcs').val(maxReturn % conversion);
alert("Return exceeds available stock!");
return;
}

// Calculate sold stock
const soldPcs = totalStock - totalReturn;
const soldCtn = Math.floor(soldPcs / conversion);
const soldRemainingPcs = soldPcs % conversion;

// Update display
$row.find('.sold-ctn').text(`${soldCtn} ${$row.find('.stock-ctn').attr('placeholder')}`);
$row.find('.sold-pcs').text(`${soldRemainingPcs} Pcs`);

// Disable "Add Rate" button if all stock is allocated
let totalAllocated = 0;
$row.find('.rate-rows tr').each(function() {
const rateCtn = parseInt($(this).find('.rate-ctn').val()) || 0;
const ratePcs = parseInt($(this).find('.rate-pcs').val()) || 0;
totalAllocated += rateCtn * conversion + ratePcs;
});

$row.find('.add-rate').prop('disabled', totalAllocated >= soldPcs);
}

function addRate(button) {
const row = $(button).closest('.product-row');
const rateRows = row.find('.rate-rows');
const soldPcs = convertToPieces(
parseInt(row.find('.sold-ctn').text()),
parseInt(row.find('.sold-pcs').text()),
row
);

let totalAllocated = 0;
rateRows.find('tr').each(function() {
totalAllocated += convertToPieces(
parseInt($(this).find('.rate-ctn').val()),
parseInt($(this).find('.rate-pcs').val()),
row
);
});

if (totalAllocated >= soldPcs) {
alert("Allocated quantity exceeds sold stock!");
return;
}

const newRow = $('').html(`



-




${rateRows.children().length === 0 ?
'' : ''}

`);
rateRows.append(newRow);
updateSoldStock(row);
}

function removeRate(button) {
const row = $(button).closest('.product-row');
const rateRows = row.find('.rate-rows');
const lastRateRow = rateRows.find('tr').last();

if (lastRateRow.length > 0) {
lastRateRow.remove(); // Remove the last rate row
updateSoldStock(row); // Update sold stock after removal
} else {
alert("No rate rows to remove!");
}
}

function selectAllQuantity(checkbox) {
const row = $(checkbox).closest('.product-row');
const rateRow = $(checkbox).closest('tr');
const conversion = row.data('conversion');
const soldCtn = parseInt(row.find('.sold-ctn').text());
const soldPcs = parseInt(row.find('.sold-pcs').text());

if (checkbox.checked) {
rateRow.find('.rate-ctn').val(soldCtn).prop('disabled', true);
rateRow.find('.rate-pcs').val(soldPcs).prop('disabled', true);
} else {
rateRow.find('.rate-ctn, .rate-pcs').val('').prop('disabled', false);
}
}

function addProductRow() {
const newRow = $('.product-row').first().clone();
newRow.find('input').val('');
newRow.find('.select2-product').remove();
newRow.find('td:first').html('');
newRow.find('.serial-number').text($('.product-row').length + 1);
newRow.find('.rate-rows').empty();
newRow.find('.total-amount, .sold-ctn, .sold-pcs, .total-dispatch-ctn, .total-dispatch-pcs').text('0');
$('#products > tbody').append(newRow);
initProductSelect(newRow.find('.product-name'));
updateSerialNumbers();
}

function removeProductRow(button) {
const rows = $('.product-row');
if (rows.length === 1) {
rows.find('input').val('');
rows.find('.rate-rows').empty();
rows.find('.select2-product').val(null).trigger('change');
updateSoldStock(rows);
updateTotalDispatch(rows);
} else {
$(button).closest('.product-row').remove();
}
updateSerialNumbers();
}

function updateSerialNumbers() {
$('.product-row .serial-number').each((i, el) =>  $(el).text(i + 1));
}

function calculateTotal() {
let grandTotal = 0;
$('.product-row').each(function() {
let rowTotal = 0;
$(this).find('.rate-rows tr').each(function() {
const ctn = parseInt($(this).find('.rate-ctn').val()) || 0;
const pcs = parseInt($(this).find('.rate-pcs').val()) || 0;
const rate = parseFloat($(this).find('.rate-value').val()) || 0;
const conversion = $(this).closest('.product-row').data('conversion') || 1;
rowTotal += ((ctn * conversion) + pcs) * rate;
});
$(this).find('.total-amount').text(`रू ${rowTotal.toFixed(2)}`);
grandTotal += rowTotal;
});
$('#grand-total').text(`रू ${grandTotal.toFixed(2)}`);
}

async function saveChallan() {
const challanData = {
date: $('#date').val(),
miti: $('#challanMiti').val(),
challan_no: $('#challanNo').val(),
salesman_id: $('#salesman').val(),
items: [],
total_amount: parseFloat($('#grand-total').text().replace('रू ', ''))
};

$('.product-row').each(function() {
const $row = $(this);
const item = {
product_id: $row.find('.product-name').val(),
stock_van: {
ctn: parseInt($row.find('.stock-ctn').val()) || 0,
pcs: parseInt($row.find('.stock-pcs').val()) || 0
},
stock_added: {
ctn: parseInt($row.find('.added-ctn').val()) || 0,
pcs: parseInt($row.find('.added-pcs').val()) || 0
},
stock_return: {
ctn: parseInt($row.find('.return-ctn').val()) || 0,
pcs: parseInt($row.find('.return-pcs').val()) || 0
},
rates: []
};

$row.find('.rate-rows tr').each(function() {
item.rates.push({
ctn: parseInt($(this).find('.rate-ctn').val()) || 0,
pcs: parseInt($(this).find('.rate-pcs').val()) || 0,
rate: parseFloat($(this).find('.rate-value').val()) || 0
});
});

challanData.items.push(item);
});

try {
const response = await fetch('/api/challan', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(challanData)
});
const result = await response.json();
alert(result.message);
if (response.ok) cancelForm();
} catch (error) {
console.error('Error:', error);
alert('Error saving challan');
}
}

function cancelForm() {
$('#salesman').val(null).trigger('change');
$('#date, #challanMiti, #challanNo').val('');
$('.product-row').each(function(index) {
if (index >  0) $(this).remove();
else {
$(this).find('input').val('');
$(this).find('.rate-rows').empty();
$(this).find('.select2-product').val(null).trigger('change');
$(this).find('.total-amount, .sold-ctn, .sold-pcs, .total-dispatch-ctn, .total-dispatch-pcs').text('0');
}
});
$('#grand-total').text('रू 0.00');
updateSerialNumbers();
}

// Event listeners for dynamic updates
$('#products').on('input', 'input', function() {
const row = $(this).closest('.product-row');
updateTotalDispatch(row);
updateSoldStock(row);
});< /code>
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap');

body {
font-family: 'Roboto', sans-serif;
margin: 20px;
font-size: 14px;
color: #333;
background-color: beige;
}

.header {
margin-bottom: 20px;
background-color: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.center-title {
text-align: center;
margin: 5px 0;
}

h2 {
font-size: 18px;
font-weight: 500;
}

h3,
h4 {
font-size: 16px;
font-weight: 400;
}

table {
width: 70%;
border-collapse: collapse;
margin-top: 10px;
background-color: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

th,
td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
font-size: 13px;
}

th {
background-color: #f2f2f2;
font-weight: 500;
}

input[type="text"],
input[type="number"],
input[type="date"] {
border: 1px solid #ccc;
padding: 5px;
border-radius: 4px;
font-size: 13px;
background-color: #f9f9f9;
}

input:focus {
border-color: #007BFF;
outline: none;
background-color: white;
}

.total-row {
font-weight: bold;
text-align: right;
}

.buttons {
margin-top: 20px;
display: flex;
gap: 10px;
}

button {
padding: 4px 8px;
font-size: 13px;
border: none;
border-radius: 4px;
background-color: #007BFF;
color: white;
cursor: pointer;
transition: background-color 0.3s ease;
}

button:hover {
background-color: #0056b3;
}

.total-amount {
font-weight: bold;
color: #007BFF;
}

.stock-inputs,
.added-inputs,
.return-inputs,
.rate-qty-inputs {
display: flex;
gap: 5px;

align-items: center;
}

.rate-table {
width: 100%;
margin-top: 10px;
border-collapse: collapse;
}

.rate-table th,
.rate-table td {
border: 1px solid #ddd;
padding: 5px;
font-size: 12px;
}

.rate-table th {
background-color: #f2f2f2;
}

.stacked {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
}

.stacked span {
display: block;
text-align: center;
}

.select2-container {
width: 200px !important;
margin-bottom: 5px;
}

.select2-product {
width: 180px !important;
}

/* Fix for button spacing */
.product-row td:last-child {
display: flex;
gap: 5px;
/* Adds spacing between buttons */
}

/* Style for Add Rate and Remove Rate buttons */
.add-rate,
.remove-rate {
margin-right: 5px;
/* Adds spacing between buttons */
}< /code>


  Store
Bau
[h4]Daily Challan[/h4]

Salesman Name: 
Challan Date: 
Challan Miti: 
Challan No: 






S.No.
Product Name
Stock in Van (Unit/Pcs)
Stock Added (Unit/Pcs)
Stock Return (Unit/Pcs)
Total Dispatch
Stock Sold (Unit/Pcs)
Rate per Unit (रू)
Total Amount (रू)
Actions




1




-






-






-





0 Unit
0 Pcs




0 Unit
0 Pcs






Quantity (Unit/Pcs)
Rate (रू)
All





Add Rate
Remove Rate


रू 0.00

Add Product
Remove Product





Back to Challan CRUD
Calculate Total
Save Challan
Cancel



Grand Total:
रू 0.00




< /code>
< /div>
< /div>
< /p>
Mein Backend:  < /p>
from flask import Flask, request, jsonify, render_template
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS

app = Flask(__name__)
CORS(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:Twlight20@localhost/inventory_db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

# Models
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), unique=True, nullable=False)
primary_unit = db.Column(db.String(20), nullable=False)  # ctn, sck, etc.
conversion_rate = db.Column(db.Integer, nullable=False)  # pieces per unit

class Salesman(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), unique=True, nullable=False)

class Challan(db.Model):
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.Date, nullable=False)
miti = db.Column(db.String(10), nullable=False)
challan_no = db.Column(db.String(50), unique=True, nullable=False)
salesman_id = db.Column(db.Integer, db.ForeignKey('salesman.id'), nullable=False)
total_amount = db.Column(db.Float, nullable=False)
items = db.relationship('ChallanItem', backref='challan', cascade="all, delete-orphan")

class ChallanItem(db.Model):
id = db.Column(db.Integer, primary_key=True)
challan_id = db.Column(db.Integer, db.ForeignKey('challan.id'), nullable=False)
product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False)
stock_van = db.Column(db.JSON, nullable=False)
stock_added = db.Column(db.JSON, nullable=False)
stock_return = db.Column(db.JSON, nullable=False)
rates = db.Column(db.JSON, nullable=False)

# Routes
@app.route('/')
def index():
return render_template('challan.html')

# Get all or search products
@app.route('/api/products', methods=['GET'])
def get_products():
search = request.args.get('q', '').strip()

if search:
products = Product.query.filter(Product.name.ilike(f'%{search}%')).all()
else:
products = Product.query.all()

if not products:
return jsonify({'message': 'No products found'}), 404

return jsonify([{'id': p.id, 'name': p.name, 'primary_unit': p.primary_unit, 'conversion_rate': p.conversion_rate} for p in products])

# Get a single product by ID
@app.route('/api/product/', methods=['GET'])
def get_product(product_id):
product = Product.query.get(product_id)

if not product:
return jsonify({'error': 'Product not found'}), 404

return jsonify({
'id': product.id,
'name': product.name,
'primary_unit': product.primary_unit,
'conversion_rate': product.conversion_rate
})

# Get all or search salesmen
@app.route('/api/salesmen', methods=['GET'])
def get_salesmen():
search = request.args.get('q', '').strip()

if search:
salesmen = Salesman.query.filter(Salesman.name.ilike(f'%{search}%')).all()
else:
salesmen = Salesman.query.all()

if not salesmen:
return jsonify({'message': 'No salesmen found'}), 404

return jsonify([{'id': s.id, 'name': s.name} for s in salesmen])

# Get a single salesman by ID
@app.route('/api/salesman/', methods=['GET'])
def get_salesman(salesman_id):
salesman = Salesman.query.get(salesman_id)

if not salesman:
return jsonify({'error': 'Salesman not found'}), 404

return jsonify({'id': salesman.id, 'name': salesman.name})

# Save a new Challan
@app.route('/api/challan', methods=['POST'])
def save_challan():
data = request.json

# Validate required fields
required_fields = ['date', 'miti', 'challan_no', 'salesman_id', 'total_amount', 'items']
for field in required_fields:
if field not in data:
return jsonify({'error': f'Missing field: {field}'}), 400

if not isinstance(data['items'], list) or len(data['items']) == 0:
return jsonify({'error': 'Items must be a non-empty list'}), 400

# Ensure the salesman exists
salesman = Salesman.query.get(data['salesman_id'])
if not salesman:
return jsonify({'error':  'Invalid salesman ID'}), 400

# Ensure the challan number is unique
existing_challan = Challan.query.filter_by(challan_no=data['challan_no']).first()
if existing_challan:
return jsonify({'error': 'Challan number already exists'}), 400

challan = Challan(
date=data['date'],
miti=data['miti'],
challan_no=data['challan_no'],
salesman_id=data['salesman_id'],
total_amount=data['total_amount']
)

for item in data['items']:
# Validate each item
required_item_fields = ['product_id', 'stock_van', 'stock_added', 'stock_return', 'rates']
for field in required_item_fields:
if field not in item:
return jsonify({'error': f'Missing item field: {field}'}), 400

# Ensure the product exists
product = Product.query.get(item['product_id'])
if not product:
return jsonify({'error': f'Invalid product ID: {item["product_id"]}'}), 400

challan_item = ChallanItem(
product_id=item['product_id'],
stock_van=item['stock_van'],
stock_added=item['stock_added'],
stock_return=item['stock_return'],
rates=item['rates']
)
challan.items.append(challan_item)

db.session.add(challan)
db.session.commit()
return jsonify({'message': 'Challan saved successfully', 'challan_id': challan.id})

if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post