Subversion Repositories munaweb

Rev

Rev 4 | Rev 6 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
<!DOCTYPE html>
2
<html lang="en">
3
 
4
<head>
5
    <title>eBay Listings Price Check</title>
6
    <meta charset="UTF-8">
7
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
    <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
9
    <link rel="icon" href="favicon.ico" type="image/x-icon">
10
 
11
    <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
12
    <link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
13
    <link rel="stylesheet" href="css/style.css">
14
    <script src="js/XMLWriter.js"></script>
15
    <script src="js/lodash.min.js"></script>
16
    <script src="js/XMLparse.js"></script>
17
    <script src="js/muna-tools.js"></script>
18
</head>
19
 
20
<body onload="return initConfig();">
21
    <div class="w3-main">
22
        <div class="w3-container w3-padding w3-margin w3-card-4">
23
            <div class="w3-container w3-gray" style="height:100px">
24
                <img class="w3-image" src="images/MUNA%20-%20Logo%20100x100.png" alt="MUNA Trading Logo" style="height:100px">
25
                <p id="connected" class="w3-xxlarge w3-right">eBay Listings Price Check
26
                    <input id="login" type="button" class="w3-btn w3-large w3-green w3-margin w3-round-large w3-ripple w3-right w3-hide" onclick="eBayLogin();" value="Login" />
27
                </p>
28
            </div>
29
 
30
            <div class="w3-row">
31
                <div>
32
                    <form id="searchForm" class="w3-container w3-light-grey w3-padding w3-small" onsubmit="return checkListingPrices();">
33
                        <div class="w3-container w3-card-2 w3-cell w3-padding">
34
                            <input id="startButton" type="button" class="w3-btn w3-large w3-black w3-margin w3-round-large w3-ripple w3-right" onclick="checkListingPrices();" value="Start" />
35
                        </div>
36
                    </form>
37
                </div>
38
                <div id="progressBarDiv" class="w3-container w3-padding w3-margin w3-card-4 w3-hide">
39
                    <h2 id="progressBarHeader"></h2>
40
                    <div class="w3-light-grey">
41
                        <div id="progressBar" class="w3-container w3-green w3-center" style="width:0%">0%</div>
42
                    </div>
43
                </div>
44
                <div id="results" class="w3-container w3-padding w3-card-4 w3-hide"></div>
45
                <div id="logging" class="w3-container w3-padding"></div>
46
            </div>
47
        </div>
48
 
49
        <footer class="w3-container w3-center w3-border-top w3-margin">
50
            Copyright &#169; 2018 MUNA Trading. All rights reserved.
51
        </footer>
52
 
53
    </div>
54
 
55
    <script>
56
 
57
// Config
58
var configMinPrice = "5.99";
59
var configDifference = 2.00;
60
var configPercentage = 20.00;
61
var configAbsoluteMinPrice = 5.00;
62
var configAdjMinPrice = 5.48;
63
var configSearchUrl = 'https://ujsoftware.linkpc.net/ebay/search.html?keyword=';
64
var configSearchUrlPart2 = '&hideDuplicateItems=on&locatedIn=WorldWide&sortOrder=PricePlusShippingLowest&results=100';
65
 
66
var pagesToProcess = 0;
67
var maxPagesToProcess = 0;
68
var pagesProcessed = 0;
69
var productIdsToProcess = 0;
70
var maxProductIdsToProcess = 0;
71
var productIdsProcessed = 0;
72
var productsToPrice = 0;
73
var maxProductsToPrice = 0;
74
var productsPriced = 0;
75
var html = [];
76
 
77
// Initialize Configuration Variables
78
function initConfig() {
79
    eBayAuthToken = readCookie();
80
    if (eBayAuthToken.length > 0) {
81
        connected();
82
    }
83
 
84
    if (eBayAuthTokenFlag === false) {
85
        var x = document.getElementById("login");
86
        if (x.className.indexOf("w3-show") == -1) {
87
            x.className += " w3-show";
88
        }
89
    }
90
}
91
 
92
function requireNewLogin() {
93
    // dummy
94
}
95
 
96
function checkListingPrices() {
97
    var x;
98
 
99
    document.getElementById("logging").innerHTML = '';
100
 
101
    x = document.getElementById("results");
102
    if (x.className.indexOf("w3-show") == -1) {
103
        x.className += " w3-show";
104
    }
105
    x.className = x.className.replace(" process-errors", "");
106
    x.innerHTML = '';
107
 
108
    initProgressBar('Retrieving Active Listings (1/3)');
109
 
110
    pagesToProcess = 1;
111
    maxPagesToProcess = 1;
112
    pagesProcessed = 0;
113
    eBaySearch(1);
114
 
115
    function checkpagesToProcess() {
116
        if (pagesToProcess > 0) {
117
            window.setTimeout(checkpagesToProcess, 100); // wait 100 milliseconds
118
        } else {
119
            findMissingProductIds();
120
        }
121
    }
122
 
123
    checkpagesToProcess();
124
}
125
 
126
// item filters for request
127
var filterarray = [];
128
var urlfilter = [];
129
 
130
// Fill the array of item filters from input form
131
function fillFilterArray() {
132
    filterarray = [];
133
    var obj = [];
134
 
135
    obj = {
136
        "name": "Seller",
137
        "value": configeBaySellerName,
138
        "paramName": "",
139
        "paramValue": ""
140
    };
141
    filterarray.push(obj);
142
 
143
    obj = {
144
        "name": "MinPrice",
145
        "value": Number(configMinPrice).toFixed(2),
146
        "paramName": "Currency",
147
        "paramValue": "USD"
148
    };
149
    filterarray.push(obj);
150
 
151
    obj = {
152
        "name": "ListingType",
153
        "value": "FixedPrice",
154
        "paramName": "",
155
        "paramValue": ""
156
    };
157
    filterarray.push(obj);
158
 
159
    urlfilter = "";
160
    // Iterate through each filter in the array
161
    for (var i = 0; i < filterarray.length; i++) {
162
        //Index each item filter in filterarray
163
        var itemfilter = filterarray[i];
164
        // Iterate through each parameter in each item filter
165
        for (var index in itemfilter) {
166
            // Check to see if the paramter has a value (some don't)
167
            if (itemfilter[index] !== "") {
168
                if (itemfilter[index] instanceof Array) {
169
                    for (var r = 0; r < itemfilter[index].length; r++) {
170
                        var value = itemfilter[index][r];
171
                        urlfilter += "&itemFilter\(" + i + "\)." + index + "\(" + r + "\)=" + value;
172
                    }
173
                } else {
174
                    urlfilter += "&itemFilter\(" + i + "\)." + index + "=" + itemfilter[index];
175
                }
176
            }
177
        }
178
    }
179
} // End fillFilterArray() function
180
 
181
var url = "";
182
 
183
function eBaySearch(pageNumber) {
184
    // Fill the filter array from form input
185
    if (pageNumber == 1) {
186
        fillFilterArray();
187
    }
188
 
189
    // Construct the request
190
    url = configeBayFinding + "?";
191
    url += "OPERATION-NAME=findItemsAdvanced";
192
    url += "&SERVICE-VERSION=" + configeBayFindingVersion;
193
    url += "&SECURITY-APPNAME=" + configAppid;
194
    url += "&GLOBAL-ID=EBAY-US";
195
    url += "&RESPONSE-DATA-FORMAT=JSON";
196
    url += "&REST-PAYLOAD";
197
    url += "&paginationInput.entriesPerPage=100";
198
    url += "&paginationInput.pageNumber=";
199
    url += pageNumber;
200
    url += urlfilter;
201
 
202
    var xhttp = new XMLHttpRequest();
203
 
204
    xhttp.onreadystatechange = function() {
205
        if (this.readyState == 4) {
206
            _cb_findItemsAdvanced(JSON.parse(this.responseText));
207
        }
208
    };
209
 
210
    xhttp.open("GET", configProxyUrl, true);
211
    xhttp.setRequestHeader("X-Proxy-Url", encodeURI(url));
212
    xhttp.send();
213
 
214
    return false;
215
}
216
 
4 - 217
function printeBayAPIError(str, root) {
2 - 218
    var x = document.getElementById("results");
219
    x.className += " process-errors";
4 - 220
    x.innerHTML += "<h2>eBay API Error (" + str + ")<h2>";
2 - 221
    x.innerHTML += "<p>Id: " + root.errorMessage[0].error[0].errorId + "<br/>";
222
    x.innerHTML += "<p>Severity: " + root.errorMessage[0].error[0].severity + "<br/>";
223
    x.innerHTML += "<p>Message: " + root.errorMessage[0].error[0].message + "</p>";
224
}
225
 
226
// Parse the response and build an HTML table to display search results
227
function _cb_findItemsAdvanced(root) {
228
    // Error Handling
229
    var response = root.findItemsAdvancedResponse[0];
230
    var ack = response.ack;
231
    if (ack != 'Success') {
4 - 232
        printeBayAPIError('Find Item', response);
2 - 233
 
234
        if (ack == 'Failure' || ack == 'PartialFailure') {
235
            --pagesToProcess;
236
            return;
237
        }
238
    }
239
 
240
    createTable(response.searchResult[0].item || [], Number(response.paginationOutput[0].pageNumber), Number(response.paginationOutput[0].totalPages));
241
 
242
   	if (Number(response.paginationOutput[0].totalPages) > Number(response.paginationOutput[0].pageNumber)) {
243
   		++maxPagesToProcess;
244
   		++pagesToProcess;
245
   		eBaySearch(Number(response.paginationOutput[0].pageNumber) + 1);
246
   	}
247
 
248
    document.getElementById("logging").innerHTML = html.join('');
249
    --pagesToProcess;
250
    ++pagesProcessed;
251
    updateProgressBar(maxPagesToProcess, pagesProcessed);
252
} // End _cb_findItemsAdvanced() function
253
 
254
 
255
function createTable(obj, pageNumber, totalPages) {
256
    if (pageNumber == 1) {
257
        document.getElementById("logging").innerHTML = '';
258
        html = [];
259
 
260
        html.push('<h3>Price Validation</h3>');
261
        html.push('<div class="w3-responsive">');
262
        html.push('<table id="itemTable" class="w3-table-all w3-hoverable css-serial">');
263
        html.push('<thead>');
264
        html.push('<tr>');
265
 
266
        html.push(tableHeader('#'));
267
        html.push(tableHeader('Item Id'));
268
        html.push(tableHeader('Thumbnail'));
269
        html.push(tableHeader('Title'));
270
        html.push(tableHeader('Product Id'));
271
        html.push(tableHeader('Price'));
272
        html.push(tableHeader('# Active Listings'));
273
        html.push(tableHeader('# Priced Lower'));
274
        html.push(tableHeader('Lowest Price'));
275
        html.push(tableHeader('Highest Price'));
276
        html.push(tableHeader('Above/Below Lowest'));
277
        html.push(tableHeader('Views'));
278
        html.push(tableHeader('Watchers'));
279
        html.push(tableHeaderHidden('Condition'));
280
        html.push(tableHeaderHidden('# Better Condition'));
281
        html.push(tableHeader('Price Adj.'));
282
        html.push(tableHeaderHidden('Best Offer'));
283
        html.push(tableHeaderHidden('MinBetterCondition'));
284
        html.push(tableHeaderHidden('BetterConditionBreakdown'));
285
        html.push(tableHeaderHidden('SameConditionBreakdown'));
286
 
287
        html.push('</tr>');
288
        html.push('</thead>');
289
        html.push('<tbody>');
290
    }
291
 
292
    for (var entry = 0; entry < obj.length; entry++) {
293
        html.push('<tr>');
294
        html.push(tableCell(''));
295
        html.push(tableCell('<a href="' + obj[entry].viewItemURL + '" target="_blank">' + obj[entry].itemId + '</a>'));
296
        html.push(tableCell('<img src="' + obj[entry].galleryURL[0].replace('http:', 'https:') + '">'));
297
        html.push(tableCell(obj[entry].title));
298
        if (obj[entry].productId !== undefined) {
299
            var str = '<a href="' + configSearchUrl;
300
            str += 'ReferenceID%3A' + obj[entry].productId[0].__value__;
301
            str += configSearchUrlPart2 + '" target="_blank">';
302
            str += obj[entry].productId[0]["@type"] + ' ' + obj[entry].productId[0].__value__;
303
            str += '</a>';
304
            html.push(tableCell(str));
305
        } else {
306
            html.push(tableCellLabel('ProductId' + obj[entry].itemId));
307
        }
308
 
309
        html.push(tableCell('$' + Number(obj[entry].sellingStatus[0].convertedCurrentPrice[0].__value__).toFixed(2)));
310
        html.push(tableCell(1));
311
        html.push(tableCell(0));
312
        html.push(tableCell('$0.00'));
313
        html.push(tableCell('$0.00'));
314
        html.push(tableCell('$0.00 (0.00%)'));
315
 
316
        html.push(tableCell(0));
317
        html.push(tableCell(obj[entry].listingInfo[0].watchCount === undefined ? 0 : Number(obj[entry].listingInfo[0].watchCount)));
318
        html.push(tableCellHidden(obj[entry].condition === undefined ? 4000 : Number(obj[entry].condition[0].conditionId)));
319
        html.push(tableCellHidden(0));
320
        html.push(tableCell('<input id="PriceAdj' + obj[entry].itemId + '" type="text" size="10"><br><input type="button" class="w3-btn w3-large w3-black w3-margin w3-round-large w3-ripple" onclick="changePrice(' + obj[entry].itemId + ');" value="Adjust Price" />'));
321
        html.push(tableCellLabelHidden('BestOffer' + obj[entry].itemId, obj[entry].listingInfo[0].bestOfferEnabled));
322
        html.push(tableCellHidden('0'));
323
        html.push(tableCellHidden('[]'));
324
        html.push(tableCellHidden('[]'));
325
 
326
        html.push('</tr>');
327
    }
328
 
329
    if (pageNumber == totalPages) {
330
        html.push('</tbody>');
331
        html.push('</table>');
332
        html.push('</div>');
333
    }
334
}
335
 
336
function setCellsAttribute(table, row, col, label) {
337
    table.rows[row].cells[col].setAttribute("id", label);
338
}
339
 
340
function sortTableDesc(tableName, column) {
341
    var table, rows, switching, i, x, y, shouldSwitch;
342
    --column; // column parameter starts with 1
343
    table = document.getElementById(tableName);
344
    switching = true;
345
    /*Make a loop that will continue until
346
    no switching has been done:*/
347
    while (switching) {
348
        //start by saying: no switching is done:
349
        switching = false;
350
        rows = table.getElementsByTagName("TR");
351
        /*Loop through all table rows (except the
352
        first, which contains table headers:*/
353
        for (i = 1; i < (rows.length - 1); i++) {
354
            //start by saying there should be no switching:
355
            shouldSwitch = false;
356
            /*Get the two elements you want to compare,
357
            one from current row and one from the next:*/
358
            x = rows[i].getElementsByTagName("TD")[column];
359
            y = rows[i + 1].getElementsByTagName("TD")[column];
360
            //check if the two rows should switch place:
361
            if (x !== undefined && (Number(x.innerHTML.substr(1)) < Number(y.innerHTML.substr(1)))) {
362
                //if so, mark as a switch and break the loop:
363
                shouldSwitch = true;
364
                break;
365
            }
366
        }
367
        if (shouldSwitch) {
368
            /*If a switch has been marked, make the switch
369
            and mark that a switch has been done:*/
370
            rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
371
            switching = true;
372
        }
373
    }
374
}
375
 
376
function findMissingProductIds() {
377
    var i;
378
    var x = document.getElementById("itemTable");
379
    var missingList = [];
380
    var viewList = [];
381
    var maxItems = 20;
382
 
383
    initProgressBar('Retrieving Product Ids (2/3)');
384
 
385
    productIdsToProcess = 0;
386
    maxProductIdsToProcess = 0;
387
    productIdsProcessed = 0;
388
 
389
    for (i = 1; i < x.rows.length; i++) {
390
        if (x.rows[i].cells[4] !== undefined && x.rows[i].cells[4].innerText.length < 1) {
391
            missingList.push(x.rows[i].cells[1].innerText);
392
        } else {
393
            var p = x.rows[i].cells[4].innerText.substr(x.rows[i].cells[4].innerText.indexOf(" ") + 1);
394
            setCellsAttribute(x, i, 5, "Price" + p);
395
            setCellsAttribute(x, i, 6, "Active" + p);
396
            setCellsAttribute(x, i, 7, "Lower" + p);
397
            setCellsAttribute(x, i, 8, "Minimum" + p);
398
            setCellsAttribute(x, i, 9, "Maximum" + p);
399
            setCellsAttribute(x, i, 11, "Views" + x.rows[i].cells[1].innerText);
400
            setCellsAttribute(x, i, 13, "Condition" + p);
401
            setCellsAttribute(x, i, 14, "BetterCondition" + p);
402
            setCellsAttribute(x, i, 17, "MinBetterCondition" + p);
403
            setCellsAttribute(x, i, 18, "BetterConditionBreakdown" + p);
404
            setCellsAttribute(x, i, 19, "SameConditionBreakdown" + p);
405
            viewList.push(x.rows[i].cells[1].innerText);
406
        }
407
    }
408
 
409
    for (i = 0;
410
        (i * maxItems) < missingList.length; i++) {
411
        ++productIdsToProcess;
412
        ++maxProductIdsToProcess;
413
        findMissingProductId(missingList.slice(i * maxItems, (i + 1) * maxItems));
414
    }
415
 
416
    for (i = 0;
417
        (i * maxItems) < viewList.length; i++) {
418
        ++productIdsToProcess;
419
        ++maxProductIdsToProcess;
420
        findViews(viewList.slice(i * maxItems, (i + 1) * maxItems));
421
    }
422
 
423
    function checkproductIdsToProcess() {
424
        if (productIdsToProcess > 0) {
425
            window.setTimeout(checkproductIdsToProcess, 100); // wait 100 milliseconds
426
        } else {
427
            priceProductIds();
428
        }
429
    }
430
 
431
    checkproductIdsToProcess();
432
}
433
 
434
function findMissingProductId(itemIdList) {
435
    var i;
436
    var xml;
437
 
438
    var xw = new XMLWriter('UTF-8', '1.0');
439
    var xhr = new XMLHttpRequest();
440
 
441
    xw.writeStartDocument();
442
    xw.writeStartElement("GetMultipleItemsRequest");
443
    xw.writeAttributeString('xmlns', 'urn:ebay:apis:eBLBaseComponents');
444
 
445
    for (i = 0; i < itemIdList.length; i++) {
446
        xw.writeElementString('ItemID', itemIdList[i]);
447
    }
448
 
449
    xw.writeElementString('IncludeSelector', 'Details');
450
    xw.writeElementString('ErrorLanguage', 'en_US');
451
    xw.writeElementString('Version', configeBayShoppingVersion);
452
    xw.writeElementString('WarningLevel', configWarningLevel);
453
 
454
    xw.writeEndElement(); /* xmlrequest */
455
    xw.writeEndDocument();
456
 
457
    xhr.open('POST', configProxyUrl, true);
458
    xhr.setRequestHeader('Content-Type', 'text/xml');
459
    xhr.setRequestHeader('X-EBAY-API-APP-NAME', configAppid);
460
    xhr.setRequestHeader('X-EBAY-API-VERSION', configeBayShoppingVersion);
461
    xhr.setRequestHeader('X-EBAY-API-CALL-NAME', 'GetMultipleItems');
462
    xhr.setRequestHeader('X-EBAY-API-SITEID', '0');
463
    xhr.setRequestHeader('X-EBAY-API-DEV-NAME', '');
464
    xhr.setRequestHeader('X-EBAY-API-CERT-NAME', '');
465
    xhr.setRequestHeader('X-EBAY-API-REQUEST-ENCODING', 'XML');
466
    xhr.setRequestHeader('X-Proxy-URL', configeBayShopping);
467
 
468
    xml = xw.flush();
469
    xw.close();
470
 
471
    xhr.onload = function() {
472
        var obj = XMLparse(xhr.responseXML);
473
 
474
        var returnCode = obj.Ack;
475
 
476
        var x = document.getElementById("results");
477
 
478
        if (returnCode == 'Success') {
479
            for (i = 0; i < obj.Item.length; i++) {
480
                var ItemID = getJsonValue(obj.Item[i].ItemID);
481
                var SKU = getJsonValue(obj.Item[i].SKU);
482
                var HitCount = getJsonValue(obj.Item[i].HitCount);
483
                var n = (SKU === undefined ? 0 : SKU.indexOf(" - "));
484
                var row;
485
                var str;
486
                var code;
487
 
488
                if (n > 0) {
489
                    code = SKU.substr(n + 3);
490
                    code = code.substr(code.indexOf(" ") + 1);
491
                    str = '<a href="' + configSearchUrl;
492
                    str += code;
493
                    str += configSearchUrlPart2 + '" target="_blank">';
494
                    str += SKU.substr(n + 3);
495
                    str += '</a>';
496
                    document.getElementById('ProductId' + ItemID).innerHTML = str;
497
                    x = document.getElementById("itemTable");
498
                    row = document.getElementById('ProductId' + ItemID).parentNode.rowIndex;
499
                    setCellsAttribute(x, row, 5, "Price" + code);
500
                    setCellsAttribute(x, row, 6, "Active" + code);
501
                    setCellsAttribute(x, row, 7, "Lower" + code);
502
                    setCellsAttribute(x, row, 8, "Minimum" + code);
503
                    setCellsAttribute(x, row, 9, "Maximum" + code);
504
                    x.rows[row].cells[11].innerHTML = HitCount;
505
                    setCellsAttribute(x, row, 13, "Condition" + code);
506
                    setCellsAttribute(x, row, 14, "BetterCondition" + code);
507
                    setCellsAttribute(x, row, 17, "MinBetterCondition" + code);
508
                    setCellsAttribute(x, row, 18, "BetterConditionBreakdown" + code);
509
                    setCellsAttribute(x, row, 19, "SameConditionBreakdown" + code);
510
                } else {
511
                    row = document.getElementById('ProductId' + ItemID).parentNode.rowIndex;
512
                    document.getElementById("itemTable").deleteRow(row);
513
                }
514
            }
515
        } else {
516
            x.className += " process-errors";
517
            x.innerHTML += '<p class="w3-red"><strong>' + returnCode + ':</strong></p>';
518
 
519
            var errors = obj.Errors;
520
            x.innerHTML += "<p>";
521
            if (errors.length > 0) {
522
                for (i = 0; i < errors.length; i++) {
523
                    x.innerHTML += errors[i].SeverityCode + " (" + errors[i].ErrorCode + "): " + escapeHtml(errors[i].LongMessage) + "<br/>";
524
                }
525
            } else {
526
                x.innerHTML += obj.Errors.SeverityCode + " (" + obj.Errors.ErrorCode + "): " + escapeHtml(obj.Errors.LongMessage) + "<br/>";
527
            }
528
            x.innerHTML += "</p>";
529
        }
530
 
531
        --productIdsToProcess;
532
        ++productIdsProcessed;
533
        updateProgressBar(maxProductIdsToProcess, productIdsProcessed);
534
    };
535
 
536
    xhr.send(xml);
537
}
538
 
539
function findViews(itemIdList) {
540
    var i;
541
    var xml;
542
 
543
    var xw = new XMLWriter('UTF-8', '1.0');
544
    var xhr = new XMLHttpRequest();
545
 
546
    xw.writeStartDocument();
547
    xw.writeStartElement("GetMultipleItemsRequest");
548
    xw.writeAttributeString('xmlns', 'urn:ebay:apis:eBLBaseComponents');
549
 
550
    for (i = 0; i < itemIdList.length; i++) {
551
        xw.writeElementString('ItemID', itemIdList[i]);
552
    }
553
 
554
    xw.writeElementString('ErrorLanguage', 'en_US');
555
    xw.writeElementString('Version', configeBayShoppingVersion);
556
    xw.writeElementString('WarningLevel', configWarningLevel);
557
 
558
    xw.writeEndElement(); /* xmlrequest */
559
    xw.writeEndDocument();
560
 
561
    xhr.open('POST', configProxyUrl, true);
562
    xhr.setRequestHeader('Content-Type', 'text/xml');
563
    xhr.setRequestHeader('X-EBAY-API-APP-NAME', configAppid);
564
    xhr.setRequestHeader('X-EBAY-API-VERSION', configeBayShoppingVersion);
565
    xhr.setRequestHeader('X-EBAY-API-CALL-NAME', 'GetMultipleItems');
566
    xhr.setRequestHeader('X-EBAY-API-SITEID', '0');
567
    xhr.setRequestHeader('X-EBAY-API-DEV-NAME', '');
568
    xhr.setRequestHeader('X-EBAY-API-CERT-NAME', '');
569
    xhr.setRequestHeader('X-EBAY-API-REQUEST-ENCODING', 'XML');
570
    xhr.setRequestHeader('X-Proxy-URL', configeBayShopping);
571
 
572
    xml = xw.flush();
573
    xw.close();
574
 
575
    xhr.onload = function() {
576
        var obj = XMLparse(xhr.responseXML);
577
 
578
        var returnCode = obj.Ack;
579
 
580
        var x = document.getElementById("results");
581
 
582
        if (returnCode == 'Success') {
583
            for (i = 0; i < obj.Item.length; i++) {
584
                var ItemID = getJsonValue(obj.Item[i].ItemID);
585
                var HitCount = getJsonValue(obj.Item[i].HitCount);
586
 
587
                document.getElementById('Views' + ItemID).innerHTML = HitCount;
588
            }
589
        } else {
590
            x.className += " process-errors";
591
            x.innerHTML += '<p class="w3-red"><strong>' + returnCode + ':</strong></p>';
592
 
593
            var errors = obj.Errors;
594
            x.innerHTML += "<p>";
595
            if (errors.length > 0) {
596
                for (i = 0; i < errors.length; i++) {
597
                    x.innerHTML += errors[i].SeverityCode + " (" + errors[i].ErrorCode + "): " + escapeHtml(errors[i].LongMessage) + "<br/>";
598
                }
599
            } else {
600
                x.innerHTML += obj.Errors.SeverityCode + " (" + obj.Errors.ErrorCode + "): " + escapeHtml(obj.Errors.LongMessage) + "<br/>";
601
            }
602
            x.innerHTML += "</p>";
603
        }
604
 
605
        --productIdsToProcess;
606
        ++productIdsProcessed;
607
        updateProgressBar(maxProductIdsToProcess, productIdsProcessed);
608
    };
609
 
610
    xhr.send(xml);
611
}
612
 
613
function priceProductIds() {
614
    var i;
615
    var price;
616
    var lowest;
617
    var difference;
618
    var percentage;
619
    var noPricedLower;
620
    var noActive;
621
    var noBetterCondition;
622
    var percLower;
623
    var x = document.getElementById("itemTable");
624
 
625
    initProgressBar('Retrieving Prices (3/3)');
626
 
627
    productsToPrice = 0;
628
    maxProductsToPrice = 0;
629
    productsPriced = 0;
630
 
631
    for (i = 1; i < x.rows.length; i++) {
4 - 632
        if (x.rows[i].cells[4].innerText.length > 0) {
633
            ++productsToPrice;
634
            ++maxProductsToPrice;
635
            findProductPrices(x.rows[i].cells[4].innerText, 1);
636
        }
2 - 637
    }
638
 
639
    function checkProductsToPrice() {
640
        if (productsToPrice > 0) {
641
            window.setTimeout(checkProductsToPrice, 100); // wait 100 milliseconds
642
        } else {
643
            /*
644
                xxxxx
645
                Minimum of 5 comparison listings
646
                (Take out lowest and highest price before calculating the average)
647
                (Don't go under $4.98)
648
                (Price items below cheapest item with better condition)
649
                Price within the first 20-25% listing (by number)
650
                (Price below the average price)
651
                adjust BIN (buy it now) when changing the price: No BIN under $10; minimum accepted 65%, auto-accepted 85+%
652
                (disregard certain sellers (for now decluttr and zuber, list could be expanded))
653
            */
654
            for (i = (x.rows.length - 1); i > 0; i--) {
655
                noPricedLower = Number(x.rows[i].cells[7].innerHTML);
656
                noActive = Number(x.rows[i].cells[6].innerHTML);
657
 
658
                if (noActive < 6) {
659
                    document.getElementById("itemTable").deleteRow(i);
660
                    continue;
661
                }
662
 
663
                if (noPricedLower > 0) {
664
                    price = Number(x.rows[i].cells[5].innerHTML.substr(1));
665
                    lowest = Number(x.rows[i].cells[8].innerHTML.substr(1));
666
                    difference = price - lowest;
667
                    percentage = 100.00 - (lowest / price * 100.00);
668
                    x.rows[i].cells[10].innerHTML = "$" + difference.toFixed(2) + " (" + percentage.toFixed(2) + "%)";
669
 
670
                    percLower = (noPricedLower / noActive) * 100.00;
671
                    if (noPricedLower > 24.99) {
672
                        x.rows[i].cells[5].style.color = "red";
673
                        x.rows[i].cells[7].style.color = "red";
674
                    } else {
675
                        document.getElementById("itemTable").deleteRow(i);
676
                        continue;
677
                    }
678
 
679
                    if (difference < configDifference || percentage < configPercentage || price < configAbsoluteMinPrice) {
680
                        document.getElementById("itemTable").deleteRow(i);
681
                        continue;
682
                    } else {
683
                        x.rows[i].cells[5].style.color = "red";
684
                        x.rows[i].cells[10].style.color = "red";
685
                    }
686
                } else if (noPricedLower === 0) {
687
                    noBetterCondition = Number(x.rows[i].cells[14].innerHTML);
688
                    if (noActive == (noBetterCondition + 1)) {
689
                        document.getElementById("itemTable").deleteRow(i);
690
                        continue;
691
                    }
692
 
693
                    price = Number(x.rows[i].cells[5].innerHTML.substr(1));
694
                    lowest = Number(x.rows[i].cells[8].innerHTML.substr(1));
695
                    difference = price - lowest;
696
                    percentage = 100.00 - (lowest / price * 100.00);
697
                    x.rows[i].cells[10].innerHTML = "$" + difference.toFixed(2) + " (" + percentage.toFixed(2) + "%)";
698
 
699
                    if ((difference * -1.00) < configDifference && (percentage * -1.00) < configPercentage) {
700
                        document.getElementById("itemTable").deleteRow(i);
701
                        continue;
702
                    } else {
703
                        x.rows[i].cells[5].style.color = "green";
704
                        x.rows[i].cells[10].style.color = "green";
705
                    }
706
                    continue;
707
                }
708
            }
709
 
710
            endProgressBar();
711
 
712
            x = document.getElementById("results");
713
            x.innerHTML += '<p><strong>Sorting Report.....</strong></p>';
714
 
715
            sortTableDesc("itemTable", 6);
716
 
717
            x.innerHTML += '<p><strong>Report Finished!</strong></p>';
718
            if (!x.className.includes("process-errors")) {
719
                setTimeout(function() {
720
                    x.className = x.className.replace(" w3-show", "");
721
                }, 3000);
722
            }
723
        }
724
    }
725
 
726
    checkProductsToPrice();
727
}
728
 
729
function findProductPrices(productId, pageNumber) {
730
    var n = productId.indexOf(" ");
731
    var productIdType = productId.substr(0, n);
4 - 732
    var keyword = productId.substr(n + 1);
2 - 733
 
734
    url = configeBayFinding + "?";
735
    if (productIdType == 'ReferenceID') {
736
        url += "OPERATION-NAME=findItemsByProduct";
737
    } else {
738
        url += "OPERATION-NAME=findItemsAdvanced";
739
    }
740
    url += "&RESPONSE-DATA-FORMAT=JSON";
741
    url += "&SECURITY-APPNAME=" + configAppid;
742
    url += "&SERVICE-VERSION=" + configeBayFindingVersion;
743
    url += "&GLOBAL-ID=EBAY-US";
744
    url += "&buyerPostalCode=";
745
    url += configZip;
746
    url += "&paginationInput.entriesPerPage=100";
747
    url += "&paginationInput.pageNumber=";
748
    url += pageNumber;
749
 
750
    if (productIdType == 'ReferenceID') {
751
        url += "&productId.@type=";
752
        url += productIdType;
753
        url += "&productId=";
4 - 754
        url += keyword;
2 - 755
    } else {
756
        url += "&keywords=";
4 - 757
        url += keyword;
2 - 758
    }
759
 
760
    url += "&itemFilter(0).name=ExcludeSeller";
761
    url += "&itemFilter(0).value=";
762
    url += configeBaySellerName;
763
 
764
    var xhttp = new XMLHttpRequest();
765
 
766
    xhttp.onreadystatechange = function() {
767
        if (this.readyState == 4) {
768
            _cb_findProductPrices(JSON.parse(this.responseText));
769
        }
770
    };
771
 
772
 
773
    xhttp.open("GET", configProxyUrl, true);
774
    xhttp.setRequestHeader("X-Proxy-Url", encodeURI(url));
775
    xhttp.send();
4 - 776
 
2 - 777
}
778
 
779
function _cb_findProductPrices(root) {
780
    var array;
781
    var response;
782
    var ack;
783
    var productId;
784
    var i;
785
    var currentPrice;
786
    var Title = "";
787
    var noLower;
788
    var noActive;
789
    var minPrice;
790
    var maxPrice;
791
    var conditionId;
792
    var currentConditionId;
793
    var noBetterCondition;
794
    var myPrice;
795
    var currentPriceInt;
796
    var minBetterCondition;
797
    var betterConditionbBreakdown = [];
798
    var sameConditionbBreakdown = [];
799
 
800
    if (root.findItemsAdvancedResponse !== undefined) {
801
        response = root.findItemsAdvancedResponse[0];
802
    } else if (root.findItemsByProductResponse !== undefined) {
803
        response = root.findItemsByProductResponse[0];
804
    } else {
805
        --productsToPrice;
806
        ++productsPriced;
807
        updateProgressBar(maxProductsToPrice, productsPriced);
808
        return;
809
    }
810
 
811
    ack = response.ack;
812
    if (ack != 'Success') {
4 - 813
        printeBayAPIError('Get Prices', response);
2 - 814
 
815
        if (ack == 'Failure' || ack == 'PartialFailure') {
816
            --productsToPrice;
817
            ++productsPriced;
818
            updateProgressBar(maxProductsToPrice, productsPriced);
819
            return;
820
        }
821
    }
822
 
823
    if (root.findItemsAdvancedResponse !== undefined) {
824
        array = typeof root.findItemsAdvancedResponse[0] != 'object' ? JSON.parse(root.findItemsAdvancedResponse[0]) : root.findItemsAdvancedResponse[0].searchResult[0].item;
825
        response = root.findItemsAdvancedResponse[0];
826
        url = new URL(response.itemSearchURL);
827
        productId = url.searchParams.get("_nkw");
828
    } else {
829
        array = typeof root.findItemsByProductResponse[0] != 'object' ? JSON.parse(root.findItemsByProductResponse[0]) : root.findItemsByProductResponse[0].searchResult[0].item;
830
        url = new URL(response.itemSearchURL);
831
        productId = url.searchParams.get("_productid");
832
    }
833
 
834
    var items = response.searchResult[0].item || [];
835
    noActive = Number(document.getElementById('Active' + productId).innerHTML);
836
    noLower = Number(document.getElementById('Lower' + productId).innerHTML);
837
    myPrice = Number(document.getElementById('Price' + productId).innerHTML.substr(1));
838
    minPrice = Number(document.getElementById('Minimum' + productId).innerHTML.substr(1));
839
    maxPrice = Number(document.getElementById('Maximum' + productId).innerHTML.substr(1));
840
    conditionId = Number(document.getElementById('Condition' + productId).innerHTML);
841
    noBetterCondition = Number(document.getElementById('BetterCondition' + productId).innerHTML);
842
    minBetterCondition = Number(document.getElementById('MinBetterCondition' + productId).innerHTML);
843
    betterConditionbBreakdown = JSON.parse(document.getElementById('BetterConditionBreakdown' + productId).innerHTML);
844
    sameConditionbBreakdown = JSON.parse(document.getElementById('SameConditionBreakdown' + productId).innerHTML);
845
 
846
    for (i = 0; i < items.length; i++) {
847
        Title = items[i].title[0].toLowerCase();
848
        if (Title.includes("disc only") > 0 ||
849
            Title.includes("disk only") > 0 ||
850
            Title.includes("only disc") > 0 ||
851
            Title.includes("only disk") > 0 ||
852
            Title.search(/dis[ck].*only/) > 0) {
853
            continue; // exclude "disc only listing
854
        }
855
 
856
        currentConditionId = (items[i].condition === undefined ? 0 : Number(items[i].condition[0].conditionId));
857
        currentPrice = Number(items[i].sellingStatus[0].convertedCurrentPrice[0].__value__);
858
        currentPriceInt = Math.ceil(currentPrice);
859
 
860
        if (currentConditionId > conditionId) {
861
            continue; // Like for like conditions only
862
        } else if (currentConditionId > conditionId) {
863
            if (minBetterCondition < 0.01 || minBetterCondition > currentPrice) {
864
                minBetterCondition = currentPrice;
865
            }
866
 
867
            ++noBetterCondition;
868
        }
869
 
870
        if (items[i].sellingStatus[0].bidCount === 0 && items[i].listingInfo[0].convertedBuyItNowPrice !== undefined) {
871
            currentPrice = Number(items[i].listingInfo[0].convertedBuyItNowPrice[0].__value__);
872
        }
873
 
874
        if (items[i].shippingInfo[0].shippingServiceCost) {
875
            currentPrice += Number(items[i].shippingInfo[0].shippingServiceCost[0].__value__);
876
        }
877
 
878
        if (currentConditionId > conditionId) {
879
            if (betterConditionbBreakdown[currentPriceInt] === undefined) {
880
                betterConditionbBreakdown[currentPriceInt] = 0;
881
            }
882
            ++betterConditionbBreakdown[currentPriceInt];
883
        } else {
884
            if (sameConditionbBreakdown[currentPriceInt] === undefined) {
885
                sameConditionbBreakdown[currentPriceInt] = 0;
886
            }
887
            ++sameConditionbBreakdown[currentPriceInt];
888
        }
889
 
890
        if (currentPrice < myPrice) {
891
            ++noLower;
892
        }
893
 
894
        if (minPrice < 0.01 || minPrice > currentPrice) {
895
            minPrice = currentPrice;
896
        }
897
 
898
        if (maxPrice < 0.01 || maxPrice < currentPrice) {
899
            maxPrice = currentPrice;
900
        }
901
 
902
        ++noActive;
903
    }
904
 
905
    document.getElementById('Active' + productId).innerHTML = noActive;
906
    document.getElementById('Lower' + productId).innerHTML = noLower;
907
    document.getElementById('Minimum' + productId).innerHTML = '$' + minPrice.toFixed(2);
908
    document.getElementById('Maximum' + productId).innerHTML = '$' + maxPrice.toFixed(2);
909
    document.getElementById('BetterCondition' + productId).innerHTML = noBetterCondition;
910
    document.getElementById('MinBetterCondition' + productId).innerHTML = minBetterCondition;
911
    document.getElementById('BetterConditionBreakdown' + productId).innerHTML = JSON.stringify(betterConditionbBreakdown);
912
    document.getElementById('SameConditionBreakdown' + productId).innerHTML = JSON.stringify(sameConditionbBreakdown);
913
 
914
    if (Number(response.paginationOutput[0].totalPages) > Number(response.paginationOutput[0].pageNumber)) {
915
        ++productsToPrice;
916
        ++maxProductsToPrice;
917
        var row = document.getElementById('Lower' + productId).parentNode.rowIndex;
918
        findProductPrices(document.getElementById("itemTable").rows[row].cells[4].innerText, Number(response.paginationOutput[0].pageNumber) + 1);
919
    }
920
 
921
    --productsToPrice;
922
    ++productsPriced;
923
    updateProgressBar(maxProductsToPrice, productsPriced);
924
}
925
 
926
function changePrice(itemId) {
927
    var i;
928
    var newPrice = parseFloat(document.getElementById('PriceAdj' + itemId).value).toFixed(2);
929
 
930
    if (isNaN(newPrice) || newPrice < configAdjMinPrice) {
931
        document.getElementById('PriceAdj' + itemId).value = '';
932
        return;
933
    }
934
 
935
    document.getElementById('PriceAdj' + itemId).value = newPrice;
936
 
937
    if (eBayAuthTokenFlag === false) {
938
        return;
939
    }
940
 
941
    var xw = new XMLWriter('UTF-8', '1.0');
942
    var xhr = new XMLHttpRequest();
943
 
944
    if (!createAddXML(xw, xhr, 'ReviseItemRequest', 'ReviseItem', itemId, newPrice)) {
945
        return;
946
    }
947
 
948
    xml = xw.flush();
949
    xw.close();
950
 
951
    xhr.onload = function() {
952
        var obj = XMLparse(xhr.responseXML);
953
 
954
        var returnCode = obj.Ack;
955
 
956
        var x = document.getElementById("results");
957
        if (x.className.indexOf("w3-show") == -1) {
958
            x.className += " w3-show";
959
        }
960
        x.className = x.className.replace(" process-errors", "");
961
 
962
        if (returnCode == 'Success' || (returnCode == 'Warning' && (obj.Errors.ErrorCode == '21917108' || obj.Errors.ErrorCode == '23007'))) {
963
            document.getElementById('PriceAdj' + itemId).style.color = "green";
964
 
965
            x.innerHTML = '<p><strong>' + returnCode + '</strong></p>';
966
 
967
            if (returnCode == 'Warning') {
968
                x.innerHTML += "<p>" + obj.Errors.SeverityCode + " (" + obj.Errors.ErrorCode + "): " + escapeHtml(obj.Errors.LongMessage) + "</p>";
969
                x.className += " process-errors";
970
            }
971
            var fees = obj.Fees;
972
            x.innerHTML += "<p>";
973
            for (i = 0; i < fees.length; i++) {
974
                if (fees[i].Fee.text !== "0.0") {
975
                    x.innerHTML += fees[i].Name + ": $" + Number(fees[i].Fee.text).toFixed(2) + "<br/>";
976
                }
977
            }
978
            x.innerHTML += "</p>";
979
 
980
            if (obj.DiscountReason) {
981
                x.innerHTML += "<p>Discount Reason: " + obj.DiscountReason + "</p>";
982
            }
983
 
984
            var recommendations = obj.ListingRecommendations;
985
            if (recommendations) {
986
                if (recommendations.length > 0) {
987
                    for (i = 0; i < recommendations.length; i++) {
988
                        x.innerHTML += decode(recommendations[i]);
989
                    }
990
                } else {
991
                    x.innerHTML += decode(recommendations);
992
                }
993
            }
994
        } else {
995
            document.getElementById('PriceAdj' + itemId).style.color = "red";
996
            x.innerHTML = "<p><strong>" + returnCode + ":</strong></p>";
997
            x.className += " process-errors";
998
 
999
            var errors = obj.Errors;
1000
            x.innerHTML += "<p>";
1001
            if (errors.length > 0) {
1002
                for (i = 0; i < errors.length; i++) {
1003
                    x.innerHTML += errors[i].SeverityCode + " (" + errors[i].ErrorCode + "): " + escapeHtml(errors[i].LongMessage) + "<br/>";
1004
                }
1005
            } else {
1006
                x.innerHTML += obj.Errors.SeverityCode + " (" + obj.Errors.ErrorCode + "): " + escapeHtml(obj.Errors.LongMessage) + "<br/>";
1007
            }
1008
 
1009
            x.innerHTML += "</p>";
1010
        }
1011
 
1012
        if (obj.Message) {
1013
            x.innerHTML += obj.Message;
1014
        }
1015
 
1016
        if (!x.className.includes("process-errors")) {
1017
            setTimeout(function() {
1018
                x.className = x.className.replace(" w3-show", "");
1019
            }, 3000);
1020
        }
1021
    };
1022
 
1023
    xhr.send(xml);
1024
}
1025
 
1026
function createAddXML(xw, xhr, xmlrequest, callname, itemId, newPrice) {
1027
    xw.writeStartDocument();
1028
    xw.writeStartElement(xmlrequest);
1029
    xw.writeAttributeString('xmlns', 'urn:ebay:apis:eBLBaseComponents');
1030
 
1031
    xw.writeStartElement('RequesterCredentials');
1032
    xw.writeElementString('eBayAuthToken', eBayAuthToken);
1033
    xw.writeEndElement(); /* RequesterCredentials */
1034
 
1035
    xw.writeStartElement('Item');
1036
 
1037
    xw.writeStartElement('StartPrice');
1038
    xw.writeAttributeString('currencyID', 'USD');
1039
    xw.writeString(newPrice);
1040
    xw.writeEndElement(); /* StartPrice */
1041
 
1042
    //xw.writeElementString('ItemID', itemId);
1043
    xw.writeString('<ItemID>' + itemId + '</ItemID>');
1044
 
1045
    if (document.getElementById('BestOffer' + itemId).innerHTML == 'true') {
1046
        if (newPrice >= 14.99) {
1047
            var autoAcceptPrice = newPrice * configAutoAcceptPrice;
1048
            var minBestOfferPrice = newPrice * configMinBestOfferPrice;
1049
 
1050
            xw.writeStartElement('BestOfferDetails');
1051
            xw.writeElementString('BestOfferEnabled', 'true');
1052
            xw.writeEndElement(); /* BestOfferDetails */
1053
            xw.writeStartElement('ListingDetails');
1054
            xw.writeStartElement('BestOfferAutoAcceptPrice');
1055
            xw.writeAttributeString('currencyID', 'USD');
1056
            xw.writeString(autoAcceptPrice.toFixed(2));
1057
            xw.writeEndElement(); /* BestOfferAutoAcceptPrice */
1058
            xw.writeStartElement('MinimumBestOfferPrice');
1059
            xw.writeAttributeString('currencyID', 'USD');
1060
            xw.writeString(minBestOfferPrice.toFixed(2));
1061
            xw.writeEndElement(); /* MinimumBestOfferPrice */
1062
            xw.writeEndElement(); /* ListingDetails */
1063
        } else {
1064
            xw.writeStartElement('BestOfferDetails');
1065
            xw.writeElementString('BestOfferEnabled', 'false');
1066
            xw.writeEndElement(); /* BestOfferDetails */
1067
        }
1068
    }
1069
 
1070
    xw.writeEndElement(); /* Item */
1071
 
1072
    xw.writeElementString('ErrorLanguage', 'en_US');
1073
    xw.writeElementString('Version', configeBayTradingVersion);
1074
    xw.writeElementString('WarningLevel', configWarningLevel);
1075
 
1076
    xw.writeEndElement(); /* xmlrequest */
1077
    xw.writeEndDocument();
1078
 
1079
    xhr.open('POST', configProxyUrl, true);
1080
    xhr.setRequestHeader('Content-Type', 'text/xml');
1081
    xhr.setRequestHeader('X-EBAY-API-APP-NAME', configAppid);
1082
    xhr.setRequestHeader('X-EBAY-API-COMPATIBILITY-LEVEL', configeBayTradingVersion);
1083
    xhr.setRequestHeader('X-EBAY-API-CALL-NAME', callname);
1084
    xhr.setRequestHeader('X-EBAY-API-SITEID', '0');
1085
    xhr.setRequestHeader('X-EBAY-API-DEV-NAME', '');
1086
    xhr.setRequestHeader('X-EBAY-API-CERT-NAME', '');
1087
    xhr.setRequestHeader('X-Proxy-URL', configServiceEndpoint);
1088
 
1089
    return true;
1090
}
1091
 
1092
function connected() {
1093
    var x;
1094
 
1095
    eBayAuthTokenFlag = true;
1096
    document.getElementById("connected").innerHTML += " (Connected)";
1097
 
1098
    x = document.getElementById("login");
1099
    x.className = x.className.replace(" w3-show", "");
1100
 
1101
    x = document.getElementById("results");
1102
    x.innerHTML = "";
1103
    x.className = x.className.replace(" w3-show", "");
1104
}
1105
 
1106
    </script>
1107
 
1108
</body>
1109
</html>