{"id":324,"date":"2013-10-03T00:42:49","date_gmt":"2013-10-03T07:42:49","guid":{"rendered":"http:\/\/bendustries.co\/wp\/?p=324"},"modified":"2019-07-13T00:32:08","modified_gmt":"2019-07-13T07:32:08","slug":"a-new-ship-to-report-adding-it-to-the-reports-screen","status":"publish","type":"post","link":"https:\/\/bendustries.co\/wp\/a-new-ship-to-report-adding-it-to-the-reports-screen\/","title":{"rendered":"A New Ship-to Report, Adding it to the Reports Screen"},"content":{"rendered":"<p>In my previous post, <a href=\"..\/wp\/a-new-ship-to-report-from-a-development-view\/\" title=\"A New Ship-To Report, From a Development View\" target=\"_blank\">A New Ship-To Report, From a Development View<\/a>, I walked through my method of developing queries in SQL Server Management Studio.  Today, we&#8217;ll take that as a starting point to add it to our reports screen.<br \/>\n<!--more--><br \/>\nAs it happens, we&#8217;ll be adding a third screen today.  We started with Warehouse Reports and Contract Reports, and we&#8217;ll be adding Customer Reports, Ship-to being our first one.<\/p>\n<p>If you want to know the honest truth of how I develop (and what I do isn&#8217;t uncommon, I suspect), it&#8217;s simple: I try to develop once and then copy and modify what came before.  To add Customer Reports, I started with Contract Reports, changed the headers and stripped out the content, and there we go &#8211; we have a brand-new interface:<\/p>\n<p><a href=\"..\/..\/images\/reports\/customerreports_first.png\" rel=\"lightbox\" title=\"Customer Reports\"><br \/>\n<img decoding=\"async\" src=\"..\/..\/images\/reports\/customerreports_first.png\" alt=\"Customer Reports\" \/><\/a><br \/>\n<em>Click for full size<\/em><\/p>\n<p>As you can see, I&#8217;ve already added the relevant JavaScript file, which is why the buttons are already styled. This is also where I realized I have redundancies in the JavaScript files for the reports screens &#8211; the Print, Collapse, and Accordion functions are identical in all of them.  That is the root of all evil in programming &#8211; the goal is to eliminate duplication wherever possible.  To that end, I&#8217;ll be fixing that soon, and moving those functions to a separate file we&#8217;ll then <em>include<\/em> in the report screen files.<\/p>\n<p>Now, as I said, I copy and modify wherever I can.  In this case, our <a href=\"..\/wp\/vendor-contract-report\/\" title=\"Vendor Contract Report\" target=\"_blank\">Vendor Contract<\/a> report is an excellent candidate, as it also uses the jMenu button to allow options for your selection criteria.  Essentially, all that&#8217;s needed is to grab that entry from the Contract Reports screen and change the names of the variables, etc.  However, notice there&#8217;s another button on the Ship-to Report, the &#8220;w\/Closed Depts&#8221; button.  This is actually a restyled checkbox, and figuring out how to get this to work was a drag.  Once I figured it out, it looks like so:<\/p>\n<p><code>&lt;div&gt;&lt;input type=\"checkbox\" name=\"chkClosed\" id=\"chkClosed\" class=\"ui-helper-hidden-accessible\"\/&gt;<br \/>\n&lt;label for=\"chkClosed\" aria-pressed=\"false\" class=\"ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only\" role=\"button\" aria-disabled=\"false\"&gt;<br \/>\n&lt;span class=\"ui-button\"&gt;w\/Closed Depts&lt;\/span&gt;<br \/>\n&lt;\/label&gt;<br \/>\n&lt;\/div&gt;<\/code><\/p>\n<p>As you might guess, we use this to toggle between including closed departments when we run a ship-to report, with a bit of back-end trickery in our PHP.<\/p>\n<p>Now, you might also have noticed that our field that normally shows us our &#8216;Last Modified&#8217; time is throwing an error. That&#8217;s because we have no files behind this.  That is, select what you want, include closed departments, etc, but the buttons that run the reports don&#8217;t do anything at the moment.  Once again, we&#8217;ll take a previously-created file and hack it into shape to serve as our ship-to file.<\/p>\n<p>We&#8217;ll start with the View file, so the Customer Reports screen will stop throwing that error.  Reaching blindly into the Contracts folder, we&#8217;ll use the contract_by_item.php file as the basis for our ship-to report.  I&#8217;ve learned the hard way that the first thing to check is the <em>check_submit<\/em> value.  For me, at least, if everything looks right but the report won&#8217;t run, it&#8217;s because I forgot to correct the <em>check_submit<\/em> value.  In this case, we&#8217;ve set it at 3 in our JS file, so we&#8217;ll change it from the 4 contract_by_item was using. <\/p>\n<p>Next, we fix the $_POST values.  contract_by_item had <\/p>\n<p><code>$mfg = sanitize($_POST['mfg']);<br \/>\n$item = sanitize($_POST['item']);<\/code><\/p>\n<p>so we&#8217;ll delete $item and change $mfg to $criteria, then change our $_POST value to &#8216;stInput&#8217; (which is the input field on our interface.)<\/p>\n<p>Next up, the SQL query itself gets replaced.  Here it gets a little trickier, as we&#8217;ll be changing the SQL query based on our selection criteria.  But, the basics of it are easy enough to get in place of the existing query.  From the <a href=\"..\/wp\/a-new-ship-to-report-from-a-development-view\/\" title=\"A New Ship-To Report, From a Development View\" target=\"_blank\">New Ship-To<\/a> file in SMSS, we&#8217;ll grab the query down to the <strong>where<\/strong> clause and paste it into our new file.<\/p>\n<p>If we were to run this right now&#8230;well, it wouldn&#8217;t go well, seeing as how we haven&#8217;t changed anything lower down in the file.  However, we&#8217;re nearly to the point of needing our first test, as we need to finish off the query by adding in the variables that make up our <strong>where<\/strong> clause.  As this is the View version of ship-to, we&#8217;ll return a fairly stripped-down version of the results, as we have a limited amount of space on-screen.  After deciding what I want to return, I&#8217;ll change the block that creates the table headers:<\/p>\n<p><code>&lt;thead&gt;<br \/>\n&lt;tr&gt;&lt;td style='font-size:12px;font-weight:bold;color:#000000;'&gt;Account&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;font-weight:bold;color:#000000;'&gt;Name&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;font-weight:bold;color:#000000;'&gt;Department&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;font-weight:bold;color:#000000;'&gt;Suite&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;font-weight:bold;color:#000000;'&gt;Street&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;font-weight:bold;color:#000000;'&gt;City&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;font-weight:bold;color:#000000;'&gt;State&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;font-weight:bold;color:#000000;'&gt;ZIP&lt;\/td&gt;<br \/>\n&lt;\/tr&gt;&lt;\/thead&gt;&lt;tbody&gt;\"<\/code><\/p>\n<p>This helps me keep straight what needs to go where when I&#8217;m changing what I&#8217;m taking from the results of the SQL query itself.  As we do a <strong>SQLSRV_FETCH_NUMERIC<\/strong> on the query, we&#8217;ll need to count out where our columns are as we change the column data.  Once that&#8217;s done, it looks like so:<\/p>\n<p><code>\"&lt;tr&gt;&lt;td style='font-size:12px;color:#000000;'&gt;$row[1]&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;color:#000000;'&gt;$row[3]&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;color:#000000;'&gt;$row[4]&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;color:#000000;'&gt;$row[7]&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;color:#000000;'&gt;$row[8]&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;color:#000000;'&gt;$row[9]&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;color:#000000;'&gt;$row[10]&lt;\/td&gt;<br \/>\n&lt;td style='font-size:12px;color:#000000;'&gt;$row[11]&lt;\/td&gt;<br \/>\n&lt;\/tr&gt;\"<\/code><\/p>\n<p>While we&#8217;re down near the bottom of the file, we&#8217;ll change the <strong>insert_timestamp<\/strong> function, as well, so we don&#8217;t skew the results of contract_by_item, by accidentally writing a ton of bogus timestamps in. This would also be the right time to jump back over to the customerreports.php file and fix the <code><\/p>\n<div class=\"subtext2\">Last run: <?php echo ret_timestamp($connect, 'ship to'); ?><\/div>\n<p><\/code> line, to be sure what the ret_timestamp function is looking for lines up with what our shipto_view.php file is writing into our log.<\/p>\n<p>All that done, we&#8217;re ready to set our first criteria for the <strong>where<\/strong> clause.  We&#8217;ll start with Account Number, since it was top of pile in the original query.  The way we do that is with another hidden submit in our customerreports.php file, named &#8216;checkST&#8217;, and a <em>menuSelect<\/em> function in our JavaScript file that retrieves the value selected.  For that, we add <code>$checkST = $_POST['stInput'];<\/code> as a new variable, and then a block something like this:<\/p>\n<p><code>if ($checkST == 'account') {<br \/>\n$limit = \"Customer.Account = \" . str_pad($criteria, 10, ' ', STR_PAD_LEFT);<br \/>\n} else {<br \/>\n$limit = '';<br \/>\n}<\/code><\/p>\n<p>We want this to give us an exact match, but we can&#8217;t easily change the amount of leading whitespace on the account number as we could in SSMS.  To get around that, we use the PHP function <em>str_pad<\/em>.  This, as you might gather from the code above, is letting us make the string 10 characters long, using spaces to pad, and padding to the left of our input string.  We&#8217;ll stick with just this one for our first test, just to see if we&#8217;re on the right track.  So upload our shipto_view.php file into the <em>\/includes\/customers<\/em> directory and see how it goes:<\/p>\n<p><img decoding=\"async\" src=\"..\/..\/images\/reports\/first_test_vst.png\" alt=\"View Ship-to First Check\" \/><\/a><\/p>\n<p>Well, that&#8217;s not good.  We forgot to check the filename we had <em>last_modified<\/em> looking for.  Fix, save, re-upload, refresh the page and we&#8217;re all good.  So, let&#8217;s actually test the report itself.<\/p>\n<p><a href=\"..\/..\/images\/reports\/second_vst.png\" rel=\"lightbox\" title=\"View Ship-to Second Check\"><br \/>\n<img decoding=\"async\" src=\"..\/..\/images\/reports\/second_vst.png\" alt=\"View Ship-to Second Check\" \/><\/a><br \/>\n<em>Click for full size<\/em><\/p>\n<p>Mm-hmm. Didn&#8217;t we already fix that?  Wasn&#8217;t that the very first thing we did?  Worse, line 54 is right in the middle of the SQL query, so we don&#8217;t have a good row number to jump to so we can fix it.  However, right below the query, the problem shows itself: <code>$params = array($mfg, $item);<\/code>.  As we&#8217;re using parameterized queries, we need to fix what we originally had.  So, we&#8217;ll change our $limit variable to <code>$limit = \"Customer.Account = \"<\/code> and add a separate variable, $full_crit, like so: <code>str_pad($criteria, 10, ' ', STR_PAD_LEFT);<\/code>.  And in the query, we&#8217;ll add <strong>(?)<\/strong> immediately after our $limit variable.  Let&#8217;s try this again:<\/p>\n<p><a href=\"..\/..\/images\/reports\/third_vst.png\" rel=\"lightbox\" title=\"View Ship-to Third Check\"><br \/>\n<img decoding=\"async\" src=\"..\/..\/images\/reports\/third_vst.png\" alt=\"View Ship-to Third Check\" \/><\/a><br \/>\n<em>Click for full size<\/em><\/p>\n<p>Occasionally these SQL errors are useful. More often, essentially it says &#8216;blah, blah, blah, you screwed up.&#8217; So, now we bust out our debugging. We&#8217;ll do it on the cheap the first time around and just <strong>echo<\/strong> what our $limit and $full_crit variables are passing.  While we&#8217;re about it, let&#8217;s check the $checkST value, too:<\/p>\n<p><code>echo 'checkST = ' . $checkST . '&lt;br \/&gt;';<br \/>\necho $limit . $full_crit . '&lt;br \/&gt;';<\/code><\/p>\n<p><a href=\"..\/..\/images\/reports\/bad_st_vst.png\" rel=\"lightbox\" title=\"Bad variable\"><br \/>\n<img decoding=\"async\" src=\"..\/..\/images\/reports\/bad_st_vst.png\" alt=\"Bad variable\" \/><\/a><br \/>\n<em>Click for full size<\/em><\/p>\n<p>Well, there we have it.  I accidentally made $checkST <code>$checkST = $_POST['stInput'];<\/code>, rather than <code>$checkST = $_POST['checkST'];<\/code>.  Boneheaded mistake, but one easily made and, more importantly, easily fixed.  Do that, run it again, and we&#8217;ve got:<\/p>\n<p><a href=\"..\/..\/images\/reports\/good_first_vst.png\" rel=\"lightbox\" title=\"Good results\"><br \/>\n<img decoding=\"async\" src=\"..\/..\/images\/reports\/good_first_vst.png\" alt=\"good results\" \/><\/a><br \/>\n<em>Click for full size<\/em><\/p>\n<p>Perfect.<\/p>\n<p>As to the other limits we query on, the procedure is essentially the same. My full block of limits for this report looks like so:<\/p>\n<p><code>if ($checkST == 'account') {<br \/>\n\t$limit = 'Customer.Account = ';<br \/>\n\t$stInput = str_pad($stInput, 10, ' ', STR_PAD_LEFT);<br \/>\n} else if ($checkST == 'rep') {<br \/>\n\t$limit = 'CustomerSalesperson.UserId = ';<br \/>\n\t$stInput = str_pad($stInput, 4, ' ', STR_PAD_LEFT);<br \/>\n} else if ($checkST == 'city') {<br \/>\n\t$limit = 'CustomerShipTo.City = ';<br \/>\n} else if ($checkST == 'state') {<br \/>\n\t$limit = 'CustomerShipTo.State = ';<br \/>\n} else if ($checkST == 'district') {<br \/>\n\t$limit = 'Customer.Region = ';<br \/>\n}<\/code> <\/p>\n<p>However, you may notice something a little funny.  That is, I need to <code>str_pad<\/code> <em>Account Number<\/em> and <em>Rep<\/em>, while I don&#8217;t for <em>City<\/em> nor <em>District<\/em>.  Why this is, given that they are char (fixed-length) fields, I can&#8217;t say, to be perfectly honest.  I discovered this by trial and error &#8211; in SSMS, I found by accident that querying on an exact city name worked without padding spaces.  Same with district &#8211; the field is 14 characters long, but my tax districts max out at 6 digits.  All that to say, sometimes you just have to play with a query until it works.  I wish it were always perfectly straight-forward, but life rarely works like that, no?<\/p>\n<p>Here I&#8217;ve given you the warts-and-all version of how I develop. What I hope you gather from this is that it gets a little ugly and messy at times, but you have the means to get it right.  A little persistence, patience, and some quality time with a search engine will lead to great success.  I find code online frequently that solves problems that at first seemed, to me, insoluble.  I sometimes get the impression that some of these people are doing this right off the top of their heads. That may be true in some cases, but I would guess that frequently development goes a bit like it does above &#8211; details get forgotten, stupid mistakes get made, and code blows up left and right.  Stick with it, though, and you&#8217;ll get it sorted.  And there&#8217;s little more satisfying than that, when you see code you wrote giving you exactly the results you need.<\/p>\n<p>As ever, I remain <img decoding=\"async\" src=\"..\/..\/images\/flux_em.png\" alt=\"\" style=\"vertical-align:middle;\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my previous post, A New Ship-To Report, From a Development View, I walked through my method of developing queries in SQL Server Management Studio. Today, we&#8217;ll take that as a starting point to add it to our reports screen.<\/p><p><a class=\"more-link btn\" href=\"https:\/\/bendustries.co\/wp\/a-new-ship-to-report-adding-it-to-the-reports-screen\/\">Continue reading<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"footnotes":""},"categories":[14,36,43,41],"tags":[40,3,29,15],"class_list":["post-324","post","type-post","status-publish","format-standard","hentry","category-mssql","category-php","category-psyops","category-sql","tag-mssql","tag-php-2","tag-psyops","tag-sql","nodate","item-wrap"],"_links":{"self":[{"href":"https:\/\/bendustries.co\/wp\/wp-json\/wp\/v2\/posts\/324","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bendustries.co\/wp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bendustries.co\/wp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bendustries.co\/wp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bendustries.co\/wp\/wp-json\/wp\/v2\/comments?post=324"}],"version-history":[{"count":12,"href":"https:\/\/bendustries.co\/wp\/wp-json\/wp\/v2\/posts\/324\/revisions"}],"predecessor-version":[{"id":450,"href":"https:\/\/bendustries.co\/wp\/wp-json\/wp\/v2\/posts\/324\/revisions\/450"}],"wp:attachment":[{"href":"https:\/\/bendustries.co\/wp\/wp-json\/wp\/v2\/media?parent=324"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bendustries.co\/wp\/wp-json\/wp\/v2\/categories?post=324"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bendustries.co\/wp\/wp-json\/wp\/v2\/tags?post=324"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}