Single SO pickup: Scan Item using UPC code

Jira Code: PROT-202
Update: To add the item scanning after the SO is scanned. Item is scanned using its UPC code.

Suitelet Script: PROT-176 SL SearchSO

/**
 * @NApiVersion 2.x
 * @NScriptType Suitelet
 * @NModuleScope SameAccount
 */
/**

* Script Description

* This suitelet to search SO and return item lines.

*/

/*******************************************************************************
 * 
 * 
 * NetSuite Name :PROT-176 SL SearchSO
 * Script ID: customscriptprot_176_sl_searchso
 * 
 * *****************************************************************************
 * 
 *  
 * $Author: Jobin & Jismi IT Services LLP $
 * 
 * DESCRIPTION
 * This suitelet to search SO and return item lines.
 * 
 * Date Created :07-03-2019
 * 
 * REVISION HISTORY Update:
 * 
 * 
 * 
 ******************************************************************************/
define(['N/search', 'N/file'],
    function(search, file) {
        var main = {
            onRequest: function(context) {
                if (context.request.method === 'GET') {
                    var index = file.load({ id: '690626' });
                    var html = index.getContents();
                    context.response.write({
                        output: html
                    });
                } else {
                    var SOid = context.request.parameters.so;
                    log.debug('SOid', SOid);
                    var results = main.SearchSO(SOid);
                    if (results)
                        context.response.write(JSON.stringify(results));
                    else
                        context.response.write('FAILED');
                }
            },
            SearchSO: function(SOID) {
                var Result = {};
                var salesorderSearchObj = search.create({
                    type: "salesorder",
                    filters: [
                        ["type", "anyof", "SalesOrd"],
                        "AND",
                        ["numbertext", "is", SOID],
                        "AND",
                        ["shipping", "is", "F"],
                        "AND",
                        ["taxline", "is", "F"],
                        "AND",
                        ["mainline", "is", "F"],
                        "AND",
                        ["quantity", "isnotempty", ""]
                    ],
                    columns: [
                        search.createColumn({ name: "internalid", join: "item", label: "Internal ID" }),
                        search.createColumn({ name: "internalid", label: "Internal ID" }),
                        search.createColumn({ name: "itemid", join: "item", label: "Name" }),
                        search.createColumn({ name: "quantity", label: "Quantity" }),
                        search.createColumn({ name: "type", join: "item", label: "Type" }),
                        search.createColumn({ name: "statusref", label: "Status" }),
                        search.createColumn({ name: "quantitypicked", label: "Quantity Picked" }),
                        search.createColumn({
                            name: "upccode",
                            join: "item",
                            label: "UPC Code"
                        })
                    ]
                });
                var searchResultCount = salesorderSearchObj.runPaged().count;

                if (searchResultCount == 0) {
                    return false;
                } else {
                    salesorderSearchObj.run().each(function(result) {
                        var itemType = result.getText({
                            name: "type",
                            join: "item",
                            label: "Type"
                        });
                        log.debug('itemType', itemType)
                        if (itemType == 'Kit/Package') {
                            var id = result.getValue({ name: "internalid", join: "item", label: "Internal ID" });
                            var qty = Number(result.getValue({ name: "quantity", label: "Quantity" }));
                            var picked = Number(result.getValue({ name: "quantitypicked", label: "Quantity Picked" }));
                            var status = result.getText({ name: "statusref", label: "Status" });
                            var internalid = result.getValue({ name: "internalid", label: "Internal ID" });
                            var set = main.SearchItem(id, qty, picked, status, Result, internalid);
                        } else {
                            var picked = Number(result.getValue({ name: "quantitypicked", label: "Quantity Picked" }));
                            var id = result.getValue({ name: "internalid", join: "item", label: "Internal ID" });
                            var obj = {
                                id: result.getValue({ name: "internalid", join: "item", label: "Internal ID" }),
                                name: result.getValue({ name: "itemid", join: "item", label: "Name" }),
                                qty: Number(result.getValue({ name: "quantity", label: "Quantity" })) - picked,
                                summary: '---',
                                status: result.getText({ name: "statusref", label: "Status" }),
                                internalid: result.getValue({ name: "internalid", label: "Internal ID" }),
                                type: result.getValue({ name: "type", join: "item", label: "Type" }),
                                upc: result.getValue({ name: "upccode", join: "item", label: "UPC Code" })
                            };
                            if (Result[id]) {
                                Result[id].qty = Result[id].qty + obj.qty;
                            } else {
                                Result[id] = obj;
                            }
                            log.debug('obj inv', obj)
                        }
                        return true;
                    });

                    return Result;
                }

            },
            SearchItem: function(id, quantity, picked, status, Result, internalid) {
                var kititemSearchObj = search.create({
                    type: "kititem",
                    filters: [
                        ["type", "anyof", "Kit"],
                        "AND",
                        ["internalidnumber", "equalto", id]
                    ],
                    columns: [
                        search.createColumn({ name: "internalid", join: "memberItem", label: "Internal ID" }),
                        search.createColumn({ name: "itemid", join: "memberItem", label: "Name" }),
                        search.createColumn({ name: "memberquantity", label: "Member Quantity" }),
                        search.createColumn({ name: "type", join: "memberItem", label: "Type" }),
                        search.createColumn({
                            name: "upccode",
                            join: "memberItem",
                            label: "UPC Code"
                        })
                    ]
                });
                var searchResultCount = kititemSearchObj.runPaged().count;
                kititemSearchObj.run().each(function(result) {
                    var obj = {
                        id: result.getValue({ name: "internalid", join: "memberItem", label: "Internal ID" }),
                        name: result.getValue({ name: "itemid", join: "memberItem", label: "Name" }),
                        qty: Number(result.getValue({ name: "memberquantity", label: "Member Quantity" })) * quantity - picked,
                        summary: '---',
                        status: status,
                        internalid: internalid,
                        type: result.getValue({ name: "type", join: "memberItem", label: "Type" }),
                        upc:result.getValue({name: "upccode", join: "memberItem", label: "UPC Code"})
                    };
                    if (Result[obj.id]) {
                        Result[obj.id].qty = Result[obj.id].qty + obj.qty;
                    } else {
                        Result[obj.id] = obj;
                    }
                    log.debug('obj kit member', obj);
                    return true;

                });

            }
        }
        for (var key in main) {
            if (typeof main[key] === 'function') {
                main[key] = trycatch(main[key], key);
            }
        }

        function trycatch(myfunction, key) {
            return function() {
                try {
                    return myfunction.apply(this, arguments);
                } catch (e) {
                    log.debug("e in  " + key, e);
                }
            }
        };
        return main;
    });

JQuery:SingleSOPickup

var SOSerachURL = "/app/site/hosting/scriptlet.nl?script=569&deploy=1";
var LotSearchURL = "/app/site/hosting/scriptlet.nl?script=570&deploy=1";
var IFCreateURL = "/app/site/hosting/scriptlet.nl?script=571&deploy=1";
var SOsearchLink = "/app/site/hosting/scriptlet.nl?script=572&deploy=1";
var ITEMS = {};
var LOTS = {};
$(function() {
	$('#LOT').hide();
	$('#Itembutton').hide();
	$('#ItemPage').hide();
	$('#submititem').hide();
	$('#searchbtn').click(function() {
		Swal.showLoading();
		ITEMS = {};
		$('#itemTable').hide();
		$('#ItemPage').hide();
		$('#Itembutton').hide();


		var SOID = $('#SOID').val().trim();
		console.log('SOID',SOID)
		if (SOID != '') {
			$.post(SOSerachURL, { so: SOID },
					function(data, status) {
				if (data == "FAILED")
					Swal.fire({
						type: 'info',
						title: 'No Result Found',
						text: 'Enter a valid SO#'
					})
					else {
						ITEMS = JSON.parse(data);
						var status = ITEMS[Object.keys(ITEMS)[0]].status;
						if (status == "Billed") {
							Swal.fire({
								type: 'info',
								title: 'SO Billed'
							})
						} else if (status == "Closed") {
							Swal.fire({
								type: 'info',
								title: 'SO Closed'
							})
						} else if (status == "Partially Fulfilled") {
							Swal.fire({
								type: 'info',
								title: 'SO Partially Fulfilled'
							})
							$('#submitso').hide();
							$('#submititem').show();
							createTable(ITEMS);

						} else{
							$('#submitso').hide();
							$('#submititem').show();
							createTable(ITEMS);
						}


						//console.log(ITEMS)
					}

			});
		} else {
			Swal.fire({
				type: 'error',
				title: 'Oops...',
				text: 'Enter SO#'
			})
		}
	});

	$('#searchbtn2').click(function(){
		Swal.showLoading();
		console.log('ITEMS',ITEMS)
		var item_id = $('#item_id').val().trim();
		console.log('item_id',item_id)
		if (item_id != ''){
			var flag=true;
			var t = keyOfObject(ITEMS, 'upc', item_id);
			console.log('t',t);
			if(t== false || !t) flag=false;
			if(Array.isArray(t))
				if(t.length==0)flag=false; 
			if(flag==false){
				Swal.fire({
					type: 'error',
					title: 'Oops...',
					text: 'Wrong UPC Code#'
				});
				return;
			}
		
			for (var key in ITEMS) {

				// console.log('ITEMS[key].name',ITEMS[key].name)
				if((ITEMS[key].upc) == item_id){

					console.log('correct item_id ' +ITEMS[key].upc,item_id)
					pickItem(key, ITEMS[key].qty, ITEMS[key].name)
					break;
					
				}
			}

//			if(flag == false){
//			Swal.fire({
//			type: 'error',
//			title: 'Oops...',
//			text: 'Wrong UPC Code#'
//			})
//			}
		}else{
			console.log('empty item_id',item_id)
			Swal.fire({
				type: 'error',
				title: 'Oops...',
				text: 'Enter UPC code#'
			})	
		}



	})

	$('#Lotcancel').click(function() {
		var summary = [];
		var LotUsed = {};

		ITEM_ID = $('#itemID').text();
		ITEMS[ITEM_ID].summary = summary;
		ITEMS[ITEM_ID]['Lots'] = LotUsed;
		createTable(ITEMS);
		$('#LOT').hide();
		$('#SOITEMS').show();
	});

	$('#Lotproceed').click(function() {
		var summary = [];
		var LotUsed = {};  
		var pick_qty=0;
		ITEM_ID = $('#itemID').text();
		console.log('LOTS',ITEMS[ITEM_ID]);
		for (var key in LOTS) {
			if (Number(LOTS[key].available) != 0) {
				var qty = Number($('#' + key).val());
				pick_qty +=qty

			}

		}
		if(ITEMS[ITEM_ID].qty>pick_qty){

			Swal.fire({
				type: 'error',
				title: 'Oops...',
				text: 'Picked Quantity is less than Quantity to Pick'
			})

			return false;
		}


		console.log('pick_qty',pick_qty);
		for (var key in LOTS) {
			if (Number(LOTS[key].available) != 0) {
				var qty = Number($('#' + key).val());
				if (qty != 0) {
					summary.push(LOTS[key].lot + ': ' + LOTS[key].bin.text + ': ' + '<b>' + qty + '</b>');
					LotUsed[key] = { LotId: key, BinID: LOTS[key].bin.value, Quantity: qty };
				}
			}
		}

		ITEMS[ITEM_ID].summary = summary;
		ITEMS[ITEM_ID]['Lots'] = LotUsed;
		//console.log('ITEMS', ITEMS);
		createTable(ITEMS);
		$('#LOT').hide();
		$('#SOITEMS').show();
	});

	$('#proceed').click(function() {
		Swal.showLoading();
		fetch(IFCreateURL, {
			method: 'POST', // or 'PUT'
			body: JSON.stringify(ITEMS), // data can be `string` or {object}!
			headers: { 'Content-Type': 'application/json' }
		}).then(function(res) {
			console.log('res', res);
			return res.json();
		})
		.then(function(response) {
			console.log('Success:', JSON.stringify(response));
			var data = response;
			//   console.log('data', data);
			if (data.text == 'SUCCESS') {
				Swal.close();
				Swal.fire({
					type: 'success',
					title: 'Item Fulfillment Created: ' + data.value,
					allowOutsideClick: false
				}).then(function() {
					window.location.reload();
				})
			} else if (data.text == 'FAIL') {
				Swal.close();
				Swal.fire({
					type: 'error',
					title: 'Pick items & Proceed'
				});
			} else {
				Swal.close();
				Swal.fire({
					type: 'error',
					title: 'Error in Creating Item fulfillment'
				});
			}

		})
		.catch(function(error) {
			console.log('Error:', error)
			Swal.close();
			Swal.fire({
				type: 'error',
				title: 'Error in Creating Item fulfillment'
			});
		})
	});
	$('#cancel').click(function() {
		window.location.reload();
	})


});

function createTable(items) {
	var create = false;
	for (var key in items) {
		if (Number(items[key].qty) > 0) {
			create = true;
			break;
		}
	}

	if (create) {
		$('#ItemPage').html('');
		var table_body = '<table id="ItemTable" class="table table-bordered table-striped table-condensed table-hover table-sm" data-show-toggle="true" data-expand-first="false" data-paging="true" data-paging-size="3">';
		table_body += "<thead>";
		table_body += "<tr>";
		table_body += " <th>Item</th>";
		table_body += "<th>Qty to Pick</th>";
		table_body += " <th data-breakpoints=\"xs sm\">Summary</th>";
		table_body += " <th>Action</th>";
		table_body += "</tr>";
		table_body += "</thead>";
		table_body += "</tbody>";

		for (var key in items) {

			if (items[key].type == 'InvtPart' && Number(items[key].qty) != 0) {
				table_body += '<tr>';
				table_body += '<td>';
				table_body += items[key].name;
				table_body += '</td>';
				table_body += '<td>';
				table_body += items[key].qty;
				table_body += '</td>';
				table_body += '<td>';
				table_body += createList(items[key].summary);
				table_body += '</td>';
				table_body += '<td>';
				if (createList(items[key].summary) == '---')
					table_body += '<div><button class="btn btn-primary btn-sm" onclick="pickItem(' + items[key].id + ',' + items[key].qty + ',' + '\'' + items[key].name + '\'' + ')">Pick</button></div>';
				else

					table_body += '<div><button class="btn btn-danger btn-sm" onclick="pickItem(' + items[key].id + ',' + items[key].qty + ',' + '\'' + items[key].name + '\'' + ')">Picked</button></div>';

				table_body += '</td>';
				table_body += '</tr>';
			}
		}
		table_body += '</tbody>';
		table_body += '</table>';

		$('#itemTable').html(table_body);
		$('#ItemTable').footable({
			"columns": [{
				"type": "text"
			},
			{
				"type": "text"
			},
			{
				"type": "html"
			}, {
				"type": "html"
			}
			]
		});

		Swal.close();
		$('#itemTable').show();
		$('#Itembutton').show();
		var SOID = $('#SOID').val().trim();
		var url=SOsearchLink+'&so='+SOID;
		$('#downloadBtn').attr('href',url);
	} else {
		Swal.close();
		Swal.fire({
			type: 'info',
			title: 'All items picked'
		});
		$('#submitso').show();
		$('#submititem').hide();
	}
}

function pickItem(ITEM_ID, ITEM_QTY, ITEM_NAME) {
	Swal.showLoading();
	$.post(LotSearchURL, { itemId: ITEM_ID },
			function(data, status) {
		if (data == "")
			Swal.fire({
				type: 'error',
				title: 'Oops...',
				text: 'Something went wrong!!'
			})
			else if (data == 'FAILED')
				Swal.fire({
					type: 'info',
					title: 'Item Not Available'
				})
				else {
					LOTS = JSON.parse(data);
					createLotTable(LOTS, ITEM_ID, ITEM_QTY, ITEM_NAME);
				}
	});
}

function createLotTable(lots, ITEM_ID, ITEM_QTY, ITEM_NAME) {
	var create = false;
	for (var key in lots) {
		if (Number(lots[key].available) > 0) {
			create = true;
			break;
		}
	}
	if (create) {
		$('#ItemPage').hide();
		var itemQty = 'Item Name: ' + ITEM_NAME + '(ID: <span id=\"itemID\">' + ITEM_ID + '</span>)' + ', Quantity to Pick: ' + ITEM_QTY;
		var itemPickedMsg = "Quantity Picked: 0";
		$('#itemName').html(itemQty);
		$('#picked').text(itemPickedMsg);
		var table_body = '<table id="lotTable" class="table table-bordered table-striped table-condensed table-hover table-sm">';
		table_body += "<thead>";
		table_body += "<tr>";
		table_body += " <th>Bin</th>";
		table_body += "<th>Lot</th>";
		table_body += " <th>Available Qty</th>";
		table_body += " <th>Pick Qty</th>";
		table_body += "</tr>";
		table_body += "</thead>";
		table_body += "</tbody>";

		for (var key in lots) {
			if (Number(lots[key].available) != 0) {
				var Onchange = "quantityPick(" + key + ",'" + escape(JSON.stringify(lots)) + "'," + ITEM_ID + "," + ITEM_QTY + ")";
				table_body += '<tr>';
				table_body += '<td>';
				table_body += lots[key].bin.text;
				table_body += '</td>';
				table_body += '<td>';
				table_body += lots[key].lot;
				table_body += '</td>';
				table_body += '<td>';
				table_body += lots[key].available;
				table_body += '</td>';
				table_body += '<td>';
				table_body += '<input type="number" id="' + key + '" min="0" max="' + ITEM_QTY + '" value="0" onchange="' + Onchange + '"></input>';
				table_body += '</td>';
				table_body += '</tr>';
			}

		}
		table_body += '</tbody>';
		table_body += '</table>';
		Swal.close();
		$('#SOITEMS').hide();
		$('#LOT').show();
		$('#LotTable').html(table_body);
	} else {
		Swal.close();
		Swal.fire({
			type: 'info',
			title: 'Item Not Available'
		})
	}
}

function quantityPick(ID, lots, ITEM_ID, ITEM_QTY) {
	var PickeQty = 0;
	lots = JSON.parse(unescape(lots));

	var SelectedQty = $('#' + ID).val();
	if (Number(SelectedQty) > Number(lots[ID].available)) {
		Swal.fire({
			type: 'info',
			title: 'Oops...',
			text: 'Selected quantity not available at inventory'
		});
		$('#' + ID).val(0);
	}
	if ((Number(SelectedQty) > Number(ITEM_QTY)) && (Number(SelectedQty) < Number(ITEM_QTY))) {
		$('#' + ID).val(ITEM_QTY);
	}
	for (var key in lots) {
		if (Number(lots[key].available) != 0) {
			var qty = Number($('#' + key).val());
			PickeQty += qty;
		}
	}
	if (Number(PickeQty) > Number(ITEM_QTY)) {
		Swal.fire({
			type: 'error',
			title: 'Oops...',
			text: 'Picked Quantity is greater than Quantity to Pick'
		})
		$('#' + ID).val(0);
		return false;
	}

	var itemPickedMsg = "Quantity Picked: " + PickeQty;
	ITEMS[ITEM_ID]['PICKED'] = PickeQty;
	ITEMS[ITEM_ID]['SetQty'] = PickeQty;
	$('#picked').text(itemPickedMsg);

}

function createList(Summary) {

	if (Summary == '---')
		return Summary;
	else if (Summary.length == 0)
		return '---';
	else {
		var list = '<ul>';
		for (var i = 0; i < Summary.length; i++) {
			list += '<li>' + Summary[i] + '</li>';
		}
		list += '</ul>';
		return list;
	}
}

function keyOfObject(obj, property, value) {
	if (typeof obj === 'object' && obj !== null)
		return Object.keys(obj).reduce(function(a, c) {
			if (obj[c][property] == value)
				a.push(c)
				return a;
		}, []);
	return false;
}

Leave a comment

Your email address will not be published. Required fields are marked *