772 lines
39 KiB
JavaScript
772 lines
39 KiB
JavaScript
frappe.pages['intake'].on_page_load = function(wrapper) {
|
|
var page = frappe.ui.make_app_page({
|
|
parent: wrapper,
|
|
title: 'Intake Station',
|
|
single_column: true
|
|
});
|
|
|
|
page.set_primary_action('New Intake', function() {
|
|
show_intake_form();
|
|
}, 'add');
|
|
|
|
page.add_inner_button('Refresh', function() {
|
|
load_recent_pallets();
|
|
});
|
|
|
|
$(wrapper).find('.layout-main-section').html(`
|
|
<div class="intake-station" style="padding: 20px;">
|
|
<div id="intake-form-container" style="display:none;">
|
|
<div class="card" style="margin-bottom: 20px;">
|
|
<div class="card-header" style="background: linear-gradient(135deg, #6f42c1, #28a745); color: white; padding: 15px;">
|
|
<img src="/files/COR_html_952bb51d.png" style="max-height: 32px; vertical-align: middle; margin-right: 10px;"><h4 style="margin:0; color: white; display: inline; vertical-align: middle;">New Intake</h4>
|
|
</div>
|
|
<div class="card-body" style="padding: 20px;">
|
|
<form id="intake-form">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<h5 style="color:#6f42c1;">📅 Dates & Source</h5>
|
|
<div class="form-group">
|
|
<label>Received Date <span class="text-danger">*</span></label>
|
|
<input type="date" id="received_date" class="form-control" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Weekday</label>
|
|
<input type="text" id="weekday" class="form-control" readonly style="background:#f8f9fa;">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Customer Number <span class="text-danger">*</span></label>
|
|
<div id="customer-number-control"></div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Driver</label>
|
|
<div id="supplier-control"></div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Company Name</label>
|
|
<input type="text" id="company_name" class="form-control">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Pickup / Drop-off</label>
|
|
<select id="pickup" class="form-control">
|
|
<option value="">—</option>
|
|
<option value="Pickup">Pickup</option>
|
|
<option value="Drop-off">Drop-off</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Notes</label>
|
|
<textarea id="notes" class="form-control" rows="3" placeholder="Any additional notes..."></textarea>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Legacy Notes</label>
|
|
<textarea id="legacy_notes" class="form-control" rows="2" style="background:#fafafa;" readonly title="Auto-filled from Customer record"></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<h5 style="color:#6f42c1;">📦 Data & Labels</h5>
|
|
<div class="form-group">
|
|
<label>Data Status</label>
|
|
<select id="data_status" class="form-control">
|
|
<option value="">—</option>
|
|
<option value="D0">D0 (Unknown)</option>
|
|
<option value="D1">D1 (Contains Data)</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>RED / R2</label>
|
|
<select id="red_r2" class="form-control">
|
|
<option value="">—</option>
|
|
<option value="RED">RED</option>
|
|
<option value="R2">R2</option>
|
|
<option value="Both">Both</option>
|
|
<option value="Neither">Neither</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="checkbox">
|
|
<label><input type="checkbox" id="needs_aor"> <strong>Needs AoR</strong> <small class="text-muted">(Agreement of Recycling)</small></label>
|
|
</div>
|
|
<div class="checkbox">
|
|
<label><input type="checkbox" id="needs_cod"> <strong>Needs COD</strong> <small class="text-muted">(Certificate of Destruction)</small></label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Barcode</label>
|
|
<input type="text" id="barcode" class="form-control" placeholder="Scan barcode...">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Total Items</label>
|
|
<input type="number" id="total_items" class="form-control" value="0" min="0">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Number of Labels</label>
|
|
<input type="number" id="num_labels" class="form-control" value="1" min="1" max="20">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<h5 style="color:#6f42c1;">👤 Contact & Financial</h5>
|
|
<div class="form-group">
|
|
<label>Contact Name</label>
|
|
<input type="text" id="contact_name" class="form-control">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Contact Persons</label>
|
|
<input type="text" id="contact_persons" class="form-control" placeholder="e.g. John Doe, Jane Smith">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Contact #</label>
|
|
<input type="tel" id="contact_number" class="form-control">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Contact Email</label>
|
|
<input type="email" id="contact_email" class="form-control">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Address</label>
|
|
<input type="text" id="address_line" class="form-control">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Hours of Operation</label>
|
|
<input type="text" id="hours_of_operation" class="form-control" placeholder="e.g. Mon-Fri 8am-5pm">
|
|
</div>
|
|
<hr>
|
|
<div class="form-group">
|
|
<label>Weight <span class="text-danger">*</span></label>
|
|
<input type="text" id="weights" class="form-control" placeholder="e.g. 340 lbs" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Invoice / Check Request</label>
|
|
<input type="text" id="invoice_check_request" class="form-control">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Amount</label>
|
|
<input type="number" id="amount" class="form-control" step="0.01" value="0">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Paid / Received</label>
|
|
<select id="paid_received" class="form-control">
|
|
<option value="">—</option>
|
|
<option value="Paid">Paid</option>
|
|
<option value="Received">Received</option>
|
|
<option value="Pending">Pending</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row" style="margin-top: 20px;">
|
|
<div class="col-md-12">
|
|
<button type="submit" class="btn btn-primary btn-lg" style="background: linear-gradient(135deg, #6f42c1, #28a745); border: none;">
|
|
<i class="fa fa-save"></i> Save Intake
|
|
</button>
|
|
<button type="button" class="btn btn-default btn-lg" id="btn-print-labels" disabled>
|
|
<i class="fa fa-print"></i> Print Labels
|
|
</button>
|
|
<button type="button" class="btn btn-default btn-lg" id="btn-cancel">
|
|
Cancel
|
|
</button>
|
|
<span id="save-status" class="ml-3" style="font-size: 1.2em;"></span>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="recent-pallets">
|
|
<div class="card">
|
|
<div class="card-header" style="background: #f8f9fa;">
|
|
<h5 style="margin:0;">Recent Pallets</h5>
|
|
</div>
|
|
<div class="card-body" style="padding: 0;">
|
|
<table class="table table-striped table-hover" id="pallet-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Status</th>
|
|
<th>Customer #</th>
|
|
<th>Driver</th>
|
|
<th>Received</th>
|
|
<th>RED/R2</th>
|
|
<th>Items</th>
|
|
<th>Weight</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="pallet-tbody">
|
|
<tr><td colspan="8" class="text-center">Loading...</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`);
|
|
|
|
// Build ERPNext Link controls for Customer Number and Supplier
|
|
setup_link_controls();
|
|
|
|
set_today_date();
|
|
load_recent_pallets();
|
|
|
|
$('#received_date').on('change', function() {
|
|
var d = new Date($(this).val() + 'T12:00:00');
|
|
var days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
|
|
$('#weekday').val(days[d.getDay()] || '');
|
|
});
|
|
|
|
$('#intake-form').on('submit', function(e) {
|
|
e.preventDefault();
|
|
save_pallet();
|
|
});
|
|
|
|
$('#btn-cancel').on('click', function() {
|
|
$('#intake-form-container').hide();
|
|
$('#recent-pallets').show();
|
|
clear_form();
|
|
});
|
|
|
|
$('#btn-print-labels').on('click', function() {
|
|
print_labels();
|
|
});
|
|
};
|
|
|
|
// ── ERPNext Link Controls ──────────────────────────────────────────────
|
|
|
|
var customer_number_control = null;
|
|
var supplier_control = null;
|
|
|
|
function setup_link_controls() {
|
|
// Customer Number — Link to Supplier, searching by name (which IS the customer number)
|
|
customer_number_control = frappe.ui.form.make_control({
|
|
parent: $('#customer-number-control'),
|
|
df: {
|
|
fieldtype: 'Link',
|
|
fieldname: 'customer_number',
|
|
options: 'Customer',
|
|
label: 'Customer Number',
|
|
reqd: 1,
|
|
placeholder: 'Search customer number...',
|
|
onchange: function() {
|
|
var val = customer_number_control.get_value();
|
|
if (val) {
|
|
fetch_customer_details(val);
|
|
} else {
|
|
clear_customer_fields();
|
|
}
|
|
}
|
|
},
|
|
only_input: true,
|
|
});
|
|
customer_number_control.refresh();
|
|
// Style to match form
|
|
$('#customer-number-control .control-input').css('margin', '0');
|
|
$('#customer-number-control .help-box').remove();
|
|
|
|
// Supplier (Driver) — Link to Supplier for driver name
|
|
supplier_control = frappe.ui.form.make_control({
|
|
parent: $('#supplier-control'),
|
|
df: {
|
|
fieldtype: 'Link',
|
|
fieldname: 'supplier',
|
|
options: 'Customer',
|
|
label: 'Driver',
|
|
placeholder: 'Search driver...',
|
|
onchange: function() {
|
|
var val = supplier_control.get_value();
|
|
if (val && val !== customer_number_control.get_value()) {
|
|
// Driver selected separately — don't override customer_number
|
|
}
|
|
}
|
|
},
|
|
only_input: true,
|
|
});
|
|
supplier_control.refresh();
|
|
$('#supplier-control .control-input').css('margin', '0');
|
|
$('#supplier-control .help-box').remove();
|
|
}
|
|
|
|
function fetch_customer_details(customer_name) {
|
|
frappe.call({
|
|
method: 'frappe.client.get',
|
|
args: {doctype: 'Customer', name: customer_name},
|
|
callback: function(r) {
|
|
if (r.message) {
|
|
var c = r.message;
|
|
// Auto-fill company name
|
|
if (c.customer_name && !$('#company_name').val()) {
|
|
$('#company_name').val(c.customer_name);
|
|
}
|
|
// Auto-fill custom CRM fields
|
|
if (c.contact_persons && !$('#contact_persons').val()) {
|
|
$('#contact_persons').val(c.contact_persons);
|
|
}
|
|
if (c.hours_of_operation && !$('#hours_of_operation').val()) {
|
|
$('#hours_of_operation').val(c.hours_of_operation);
|
|
}
|
|
if (c.legacy_notes && !$('#legacy_notes').val()) {
|
|
$('#legacy_notes').val(c.legacy_notes);
|
|
}
|
|
// Driver is independent — don't auto-populate from customer number
|
|
|
|
// Fill contact fields from Supplier doc's native fields first
|
|
// ERPNext auto-populates these from the primary Contact/Address
|
|
if (c.customer_primary_contact) {
|
|
// Fetch the Contact doc for name/phone/email
|
|
frappe.call({
|
|
method: 'frappe.client.get',
|
|
args: {doctype: 'Contact', name: c.customer_primary_contact},
|
|
callback: function(cr) {
|
|
if (cr.message) {
|
|
var ct = cr.message;
|
|
var full_name = [ct.first_name, ct.last_name].filter(Boolean).join(' ');
|
|
if (full_name && !$('#contact_name').val()) {
|
|
$('#contact_name').val(full_name);
|
|
}
|
|
if (ct.email_id && !$('#contact_email').val()) {
|
|
$('#contact_email').val(ct.email_id);
|
|
}
|
|
if (ct.phone && !$('#contact_number').val()) {
|
|
$('#contact_number').val(ct.phone);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
// Fallback: use Supplier-level fields (mobile_no, email_id)
|
|
if (c.mobile_no && !$('#contact_number').val()) {
|
|
$('#contact_number').val(c.mobile_no);
|
|
}
|
|
if (c.email_id && !$('#contact_email').val()) {
|
|
$('#contact_email').val(c.email_id);
|
|
}
|
|
|
|
// Last resort: search for any linked Contact
|
|
frappe.call({
|
|
method: 'frappe.client.get_list',
|
|
args: {
|
|
doctype: 'Contact',
|
|
filters: [['Dynamic Link', 'link_name', '=', customer_name]],
|
|
fields: ['name', 'first_name', 'last_name', 'email_id', 'phone'],
|
|
limit_page_length: 1
|
|
},
|
|
callback: function(cr) {
|
|
if (cr.message && cr.message.length > 0) {
|
|
var c = cr.message[0];
|
|
var full_name = [c.first_name, c.last_name].filter(Boolean).join(' ');
|
|
if (full_name && !$('#contact_name').val()) {
|
|
$('#contact_name').val(full_name);
|
|
}
|
|
if (c.email_id && !$('#contact_email').val()) {
|
|
$('#contact_email').val(c.email_id);
|
|
}
|
|
if (c.phone && !$('#contact_number').val()) {
|
|
$('#contact_number').val(c.phone);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Fill address from Supplier doc's primary_address or linked Address
|
|
if (c.primary_address && !$('#address_line').val()) {
|
|
$('#address_line').val(c.primary_address);
|
|
} else if (c.customer_primary_address) {
|
|
frappe.call({
|
|
method: 'frappe.client.get',
|
|
args: {doctype: 'Address', name: c.customer_primary_address},
|
|
callback: function(ar) {
|
|
if (ar.message) {
|
|
var a = ar.message;
|
|
var addr = [a.address_line1, a.address_line2, a.city, a.state].filter(Boolean).join(', ');
|
|
if (addr && !$('#address_line').val()) {
|
|
$('#address_line').val(addr);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
// Fallback: search for any linked Address
|
|
frappe.call({
|
|
method: 'frappe.client.get_list',
|
|
args: {
|
|
doctype: 'Address',
|
|
filters: [['Dynamic Link', 'link_name', '=', customer_name]],
|
|
fields: ['name', 'address_line1', 'city', 'state'],
|
|
limit_page_length: 1
|
|
},
|
|
callback: function(ar) {
|
|
if (ar.message && ar.message.length > 0) {
|
|
var a = ar.message[0];
|
|
var addr = [a.address_line1, a.city, a.state].filter(Boolean).join(', ');
|
|
if (addr && !$('#address_line').val()) {
|
|
$('#address_line').val(addr);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function clear_customer_fields() {
|
|
$('#company_name').val('');
|
|
$('#contact_name').val('');
|
|
$('#contact_number').val('');
|
|
$('#contact_email').val('');
|
|
$('#address_line').val('');
|
|
if (supplier_control) supplier_control.set_value('');
|
|
}
|
|
|
|
// ── Form Helpers ──────────────────────────────────────────────────────
|
|
|
|
function set_today_date() {
|
|
var today = new Date().toISOString().split('T')[0];
|
|
$('#received_date').val(today);
|
|
$('#received_date').trigger('change');
|
|
}
|
|
|
|
function show_intake_form() {
|
|
$('#intake-form-container').show();
|
|
$('#recent-pallets').hide();
|
|
set_today_date();
|
|
// Focus the customer number control
|
|
setTimeout(function() {
|
|
if (customer_number_control) {
|
|
customer_number_control.$input.focus();
|
|
}
|
|
}, 200);
|
|
}
|
|
|
|
function clear_form() {
|
|
$('#intake-form input[type="text"], #intake-form input[type="tel"], #intake-form input[type="email"], #intake-form input[type="number"], #intake-form input[type="date"], #intake-form textarea').val('');
|
|
$('#legacy_notes').val('');
|
|
$('#intake-form select').val('');
|
|
$('#total_items').val('0');
|
|
$('#num_labels').val('1');
|
|
$('#amount').val('0');
|
|
$('#needs_aor').prop('checked', false);
|
|
$('#needs_cod').prop('checked', false);
|
|
$('#btn-print-labels').prop('disabled', true);
|
|
$('#save-status').text('');
|
|
$('#intake-form-container').data('pallet-name', '');
|
|
if (customer_number_control) customer_number_control.set_value('');
|
|
if (supplier_control) supplier_control.set_value('');
|
|
}
|
|
|
|
function save_pallet() {
|
|
var pallet_name = $('#intake-form-container').data('pallet-name');
|
|
var is_new = !pallet_name;
|
|
|
|
var data = {
|
|
doctype: 'Pallet',
|
|
received_date: $('#received_date').val(),
|
|
customer_number: customer_number_control ? customer_number_control.get_value() : '',
|
|
customer: customer_number_control ? customer_number_control.get_value() : '',
|
|
supplier: supplier_control ? supplier_control.get_value() : '',
|
|
company_name: $('#company_name').val(),
|
|
pickup: $('#pickup').val(),
|
|
data_status: $('#data_status').val(),
|
|
red_r2: $('#red_r2').val(),
|
|
barcode: $('#barcode').val(),
|
|
total_items: parseInt($('#total_items').val()) || 0,
|
|
num_labels: parseInt($('#num_labels').val()) || 1,
|
|
contact_name: $('#contact_name').val(),
|
|
contact_persons: $('#contact_persons').val(),
|
|
contact_number: $('#contact_number').val(),
|
|
contact_email: $('#contact_email').val(),
|
|
address_line: $('#address_line').val(),
|
|
hours_of_operation: $('#hours_of_operation').val(),
|
|
legacy_notes: $('#legacy_notes').val(),
|
|
weights: $('#weights').val(),
|
|
invoice_check_request: $('#invoice_check_request').val(),
|
|
amount: parseFloat($('#amount').val()) || 0,
|
|
paid_received: $('#paid_received').val(),
|
|
needs_aor: $('#needs_aor').is(':checked') ? 1 : 0,
|
|
needs_cod: $('#needs_cod').is(':checked') ? 1 : 0,
|
|
notes: $('#notes').val(),
|
|
status: 'Received'
|
|
};
|
|
|
|
if (!is_new) {
|
|
data.name = pallet_name;
|
|
}
|
|
|
|
frappe.call({
|
|
method: is_new ? 'frappe.client.insert' : 'frappe.client.update',
|
|
args: { doc: data },
|
|
callback: function(r) {
|
|
if (r.message) {
|
|
var name = r.message.name;
|
|
$('#save-status').html('<span class="text-success"><i class="fa fa-check"></i> Saved as Intake ' + name + '</span>');
|
|
$('#btn-print-labels').prop('disabled', false);
|
|
if (is_new) {
|
|
$('#intake-form-container').data('pallet-name', name);
|
|
}
|
|
}
|
|
},
|
|
error: function(r) {
|
|
var msg = 'Unknown error';
|
|
if (r && r._server_messages) {
|
|
try {
|
|
var msgs = JSON.parse(r._server_messages);
|
|
if (msgs && msgs.length) {
|
|
var errObj = JSON.parse(msgs[0]);
|
|
msg = errObj.message || msg;
|
|
}
|
|
} catch(e) {}
|
|
}
|
|
$('#save-status').html('<span class="text-danger"><i class="fa fa-exclamation"></i> Error: ' + msg + '</span>');
|
|
}
|
|
});
|
|
}
|
|
|
|
function load_recent_pallets() {
|
|
frappe.call({
|
|
method: 'frappe.client.get_list',
|
|
args: {
|
|
doctype: 'Pallet',
|
|
fields: ['name', 'pallet_number', 'status', 'customer_number', 'company_name', 'supplier', 'received_date', 'red_r2', 'total_items', 'weights', 'notes', 'needs_aor', 'needs_cod'],
|
|
limit_page_length: 20,
|
|
order_by: 'creation desc'
|
|
},
|
|
callback: function(r) {
|
|
var tbody = $('#pallet-tbody');
|
|
tbody.empty();
|
|
if (!r.message || r.message.length === 0) {
|
|
tbody.append('<tr><td colspan="8" class="text-center">No pallets yet</td></tr>');
|
|
return;
|
|
}
|
|
r.message.forEach(function(p) {
|
|
var status_class = {
|
|
'Received': 'info',
|
|
'Sorting': 'warning',
|
|
'Processing': 'primary',
|
|
'Complete': 'success',
|
|
'Shipped': 'default'
|
|
}[p.status] || 'default';
|
|
|
|
tbody.append(
|
|
'<tr>' +
|
|
'<td><span class="label label-' + status_class + '">' + (p.status || 'Received') + '</span></td>' +
|
|
'<td><strong>' + (p.customer_number || '') + '</strong></td>' +
|
|
'<td>' + (p.supplier || '') + '</td>' +
|
|
'<td>' + (p.received_date || '') + '</td>' +
|
|
'<td>' + (p.red_r2 || '') +
|
|
(p.needs_aor ? ' <span class="label label-warning">AoR</span>' : '') +
|
|
(p.needs_cod ? ' <span class="label label-danger">COD</span>' : '') +
|
|
'</td>' +
|
|
'<td>' + (p.total_items || 0) + '</td>' +
|
|
'<td>' + (p.weights || '') + '</td>' +
|
|
'<td>' +
|
|
'<button class="btn btn-xs btn-default" onclick="edit_pallet(\'' + p.name + '\')"><i class="fa fa-edit"></i></button> ' +
|
|
'<button class="btn btn-xs btn-default" onclick="print_pallet_labels(\'' + p.name + '\')"><i class="fa fa-print"></i></button>' +
|
|
'</td>' +
|
|
'</tr>'
|
|
);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
function edit_pallet(name) {
|
|
frappe.call({
|
|
method: 'frappe.client.get',
|
|
args: {doctype: 'Pallet', name: name},
|
|
callback: function(r) {
|
|
if (r.message) {
|
|
var d = r.message;
|
|
$('#intake-form-container').show();
|
|
$('#recent-pallets').hide();
|
|
$('#intake-form-container').data('pallet-name', name);
|
|
$('#received_date').val(d.received_date || '');
|
|
if (customer_number_control) customer_number_control.set_value(d.customer_number || '');
|
|
if (supplier_control) supplier_control.set_value(d.supplier || '');
|
|
$('#company_name').val(d.company_name || '');
|
|
$('#pickup').val(d.pickup || '');
|
|
$('#data_status').val(d.data_status || '');
|
|
$('#red_r2').val(d.red_r2 || '');
|
|
$('#barcode').val(d.barcode || '');
|
|
$('#total_items').val(d.total_items || 0);
|
|
$('#num_labels').val(d.num_labels || 1);
|
|
$('#contact_name').val(d.contact_name || '');
|
|
$('#contact_number').val(d.contact_number || '');
|
|
$('#contact_email').val(d.contact_email || '');
|
|
$('#address_line').val(d.address_line || '');
|
|
$('#weights').val(d.weights || '');
|
|
$('#invoice_check_request').val(d.invoice_check_request || '');
|
|
$('#amount').val(d.amount || 0);
|
|
$('#paid_received').val(d.paid_received || '');
|
|
$('#needs_aor').prop('checked', d.needs_aor === 1);
|
|
$('#needs_cod').prop('checked', d.needs_cod === 1);
|
|
$('#notes').val(d.notes || '');
|
|
$('#received_date').trigger('change');
|
|
$('#btn-print-labels').prop('disabled', false);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function print_labels() {
|
|
var pallet_name = $('#intake-form-container').data('pallet-name');
|
|
if (!pallet_name) return;
|
|
print_pallet_labels(pallet_name);
|
|
}
|
|
|
|
function print_pallet_labels(name) {
|
|
frappe.call({
|
|
method: 'frappe.client.get',
|
|
args: {doctype: 'Pallet', name: name},
|
|
callback: function(r) {
|
|
if (r.message) {
|
|
generate_zpl_label(r.message);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function generate_zpl_label(d) {
|
|
var label_count = d.num_labels || 1;
|
|
var date_str = d.received_date || '';
|
|
var driver = d.supplier || '';
|
|
var customer_num = d.customer_number || '';
|
|
var red_r2 = d.red_r2 || '';
|
|
var weight = d.weights || '';
|
|
var pallet_num = d.pallet_number || d.name || '';
|
|
var qr_url = window.location.origin + '/app/pallet/' + (d.name || pallet_num);
|
|
|
|
var logo_url = window.location.origin + '/files/COR_html_952bb51d.png';
|
|
|
|
var labels_html = '';
|
|
for (var i = 1; i <= label_count; i++) {
|
|
labels_html += '<div class="label-card">';
|
|
labels_html += '<div class="label-header"><img src="' + logo_url + '" style="max-height: 36px; vertical-align: middle;"> <span style="vertical-align: middle;">WESTECH RECYCLERS</span></div>';
|
|
labels_html += '<div class="label-body">';
|
|
labels_html += '<div class="label-top">';
|
|
labels_html += '<div class="label-info">';
|
|
labels_html += '<div class="label-row"><span class="label-field">Pallet #:</span> <span class="label-value">' + pallet_num + '</span></div>';
|
|
if (customer_num) {
|
|
labels_html += '<div class="label-row"><span class="label-field">Customer #:</span> <span class="label-value">' + customer_num + '</span></div>';
|
|
}
|
|
labels_html += '<div class="label-row"><span class="label-field">Received:</span> <span class="label-value">' + date_str + '</span></div>';
|
|
labels_html += '<div class="label-row"><span class="label-field">Driver:</span> <span class="label-value">' + driver + '</span></div>';
|
|
labels_html += '<div class="label-row"><span class="label-field">Weight:</span> <span class="label-value">' + weight + '</span></div>';
|
|
labels_html += '<div class="label-row"><span class="label-field">Items:</span> <span class="label-value">' + (d.total_items || 0) + '</span></div>';
|
|
labels_html += '</div>';
|
|
labels_html += '<div class="label-qr" id="qr-' + i + '"></div>';
|
|
labels_html += '</div>';
|
|
if (red_r2) {
|
|
labels_html += '<div class="label-badge">' + red_r2 + '</div>';
|
|
}
|
|
labels_html += '<div class="label-footer">Label ' + i + ' of ' + label_count + '</div>';
|
|
labels_html += '</div></div>';
|
|
}
|
|
|
|
var existing = document.getElementById('label-preview-overlay');
|
|
if (existing) existing.remove();
|
|
|
|
var overlay = document.createElement('div');
|
|
overlay.id = 'label-preview-overlay';
|
|
overlay.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.6);z-index:9999;display:flex;align-items:center;justify-content:center;';
|
|
|
|
var modal = document.createElement('div');
|
|
modal.style.cssText = 'background:#fff;border-radius:8px;padding:20px;max-height:90vh;overflow-y:auto;box-shadow:0 4px 20px rgba(0,0,0,0.3);max-width:95vw;';
|
|
|
|
var title = document.createElement('h3');
|
|
title.textContent = 'Label Preview — Pallet ' + pallet_num + ' (' + label_count + ' label' + (label_count > 1 ? 's' : '') + ')';
|
|
title.style.cssText = 'margin:0 0 15px 0;font-size:16pt;';
|
|
|
|
var btnGroup = document.createElement('div');
|
|
btnGroup.style.cssText = 'margin-bottom:15px;display:flex;gap:10px;';
|
|
|
|
var printBtn = document.createElement('button');
|
|
printBtn.className = 'btn btn-primary';
|
|
printBtn.innerHTML = '<i class="fa fa-print"></i> Print Labels';
|
|
printBtn.onclick = function() {
|
|
var pw = window.open('', '_blank');
|
|
pw.document.write('<html><head><title>Labels — Pallet ' + pallet_num + '</title>');
|
|
pw.document.write('<script src="https://cdn.jsdelivr.net/npm/qrcode-generator@1.4.4/qrcode.min.js"><\/script>');
|
|
pw.document.write('<style>');
|
|
pw.document.write('@page { size: 4in 6in; margin: 0; }');
|
|
pw.document.write('body { font-family: Arial, Helvetica, sans-serif; margin: 0; padding: 5mm; }');
|
|
pw.document.write('.label-card { width: 100%; max-width: 3.5in; border: 2px solid #000; margin-bottom: 10px; page-break-inside: avoid; }');
|
|
pw.document.write('.label-header { background: #000; color: #fff; font-size: 18pt; font-weight: bold; text-align: center; padding: 6px 0; letter-spacing: 2px; }');
|
|
pw.document.write('.label-body { padding: 8px 12px; }');
|
|
pw.document.write('.label-top { display: flex; justify-content: space-between; align-items: flex-start; }');
|
|
pw.document.write('.label-info { flex: 1; }');
|
|
pw.document.write('.label-qr { flex-shrink: 0; margin-left: 10px; }');
|
|
pw.document.write('.label-qr table { border-collapse: collapse; }');
|
|
pw.document.write('.label-qr td { width: 4px; height: 4px; }');
|
|
pw.document.write('.label-row { font-size: 13pt; padding: 2px 0; }');
|
|
pw.document.write('.label-field { font-weight: bold; display: inline-block; min-width: 100px; }');
|
|
pw.document.write('.label-value { }');
|
|
pw.document.write('.label-badge { margin-top: 6px; padding: 4px 12px; background: #d9534f; color: #fff; font-size: 14pt; font-weight: bold; text-align: center; border-radius: 3px; display: inline-block; }');
|
|
pw.document.write('.label-footer { font-size: 10pt; color: #666; text-align: center; margin-top: 4px; }');
|
|
pw.document.write('@media print { body { padding: 0; } .label-card { margin-bottom: 0; page-break-after: always; } .label-card:last-child { page-break-after: auto; } }');
|
|
pw.document.write('</style></head><body>');
|
|
pw.document.write(labels_html);
|
|
pw.document.write('<script>');
|
|
pw.document.write('var qr_url = ' + JSON.stringify(qr_url) + ';');
|
|
pw.document.write('var qr = qrcode(0, "M"); qr.addData(qr_url); qr.make();');
|
|
pw.document.write('for (var i = 1; i <= ' + label_count + '; i++) { var el = document.getElementById("qr-" + i); if (el) { el.innerHTML = qr.createImgTag(3, 0); } }');
|
|
pw.document.write('setTimeout(function() { window.print(); }, 500);');
|
|
pw.document.write('<\/script>');
|
|
pw.document.write('</body></html>');
|
|
pw.document.close();
|
|
};
|
|
|
|
var closeBtn = document.createElement('button');
|
|
closeBtn.className = 'btn btn-default';
|
|
closeBtn.textContent = 'Cancel';
|
|
closeBtn.onclick = function() {
|
|
overlay.remove();
|
|
};
|
|
|
|
btnGroup.appendChild(printBtn);
|
|
btnGroup.appendChild(closeBtn);
|
|
|
|
var previewArea = document.createElement('div');
|
|
previewArea.style.cssText = 'display:flex;flex-wrap:wrap;gap:15px;justify-content:center;';
|
|
previewArea.innerHTML = labels_html;
|
|
|
|
var previewStyles = document.createElement('style');
|
|
previewStyles.textContent =
|
|
'#label-preview-overlay .label-card { width: 4in; border: 2px solid #000; background: #fff; box-shadow: 1px 1px 6px rgba(0,0,0,0.15); }' +
|
|
'#label-preview-overlay .label-header { background: #000; color: #fff; font-size: 18pt; font-weight: bold; text-align: center; padding: 6px 0; letter-spacing: 2px; }' +
|
|
'#label-preview-overlay .label-body { padding: 8px 12px; }' +
|
|
'#label-preview-overlay .label-top { display: flex; justify-content: space-between; align-items: flex-start; }' +
|
|
'#label-preview-overlay .label-info { flex: 1; }' +
|
|
'#label-preview-overlay .label-qr { flex-shrink: 0; margin-left: 10px; }' +
|
|
'#label-preview-overlay .label-row { font-size: 13pt; padding: 2px 0; }' +
|
|
'#label-preview-overlay .label-field { font-weight: bold; display: inline-block; min-width: 100px; }' +
|
|
'#label-preview-overlay .label-badge { margin-top: 6px; padding: 4px 12px; background: #d9534f; color: #fff; font-size: 14pt; font-weight: bold; text-align: center; border-radius: 3px; display: inline-block; }' +
|
|
'#label-preview-overlay .label-footer { font-size: 10pt; color: #666; text-align: center; margin-top: 4px; }';
|
|
|
|
modal.appendChild(title);
|
|
modal.appendChild(btnGroup);
|
|
modal.appendChild(previewStyles);
|
|
modal.appendChild(previewArea);
|
|
overlay.appendChild(modal);
|
|
document.body.appendChild(overlay);
|
|
|
|
// Generate QR codes in preview
|
|
var script = document.createElement('script');
|
|
script.src = 'https://cdn.jsdelivr.net/npm/qrcode-generator@1.4.4/qrcode.min.js';
|
|
script.onload = function() {
|
|
var qr = qrcode(0, 'M');
|
|
qr.addData(qr_url);
|
|
qr.make();
|
|
for (var i = 1; i <= label_count; i++) {
|
|
var el = document.getElementById('qr-' + i);
|
|
if (el) el.innerHTML = qr.createImgTag(3, 0);
|
|
}
|
|
};
|
|
document.head.appendChild(script);
|
|
|
|
overlay.addEventListener('click', function(e) {
|
|
if (e.target === overlay) overlay.remove();
|
|
});
|
|
}
|
|
|
|
window.edit_pallet = edit_pallet;
|
|
window.print_pallet_labels = print_pallet_labels; |