Jump to content

DeX

Members
  • Posts

    258
  • Joined

  • Last visited

Posts posted by DeX

  1. I wasn't necessarily going to build setters and getters for every single database column. For example, if I have a quote I need to display on the page, I would build a customer object and set all the customer details in that so the getters can retrieve it to display on the page, it's only name, address and phone number. Then I would have a quote object which would set things like the quote price, the quote expiry date and a list of all the upgrade options to show on the quote, along with their attributes like width, height and quantity.

     

    Then when doing purchase orders, I would build a bill of materials (BOM) object that would contain all individual building products and their attributes. Is this wrong? I'm mostly wondering how to separate the model into multiple models because I mainly just have one right now with all the methods in it.

  2. I've been working with what I thought was MVC for quite a while but now after researching it some more, it appears I may have been wrong all along. I think I have been using the model incorrectly. Is my new way of thinking now correct?

     

    Model: These are like objects that hold data during the session (page load). It can also dump the data to the database but is mainly used to hold data related to a specific object for use throughout the current page load.

     

    Controller: There will usually only be one as it is like a gatekeeper that directs requests to the proper model.

     

    View: These will usually be the .php pages themselves but for views that are reused, it can be an isolated class which generates HTML code (like loading a select element with user names).

     

    I have built a program where a quote is requested by the user and the program has to go to the database in order to get the details of the quote to display them on screen. Right now my view is making the request through the controller to the model and the model is fetching each piece of requested information from the database, then passing it back through to the view as needed. Because the page can show the same information in various places, the same database call by the model can be made more than once for that specific information. Should I be making a request for the entire quote, building a quote object with the model and then passing that entire object back to the view to be used instead? This will introduce a lot of getter/setts methods of which I currently have none.

     

    I'm assuming I would have a customer model which would build a customer object and return that. Then a quote model would build a quote object and return that. Same for purchase orders and users, all which will have information appearing on the quote or purchase order.

     

    Thanks a lot, I'm really trying to research this as much as I can and get it correct.

  3. Is the loop creating duplicate select lists of the same data? If so, you should call the process (I assume from a DB) to get the values for the select lists one time. Then, unless each list will have different default values, create the list options one-time. Then populate the list of options in each of the unique select lists. If each select list needs a different default value, then create the lists options independently from the data that was retrieved before the loop.

    At times, yes. Some SELECT elements will be duplicated on more than one screen, like the list of users. That can be used to assign a quote to a salesman or it can be used on the user management screen in the admin section.

  4. Ideally, the controller is in charge of shuffling data between the model and view, and has no knowledge of how the data is stored (model) or how it's presented externally (view). So it should gather together the information that the view will need, and the view should take that data and arrange it into whatever HTML format is necessary.

     

    The controller is probably a class and the view is probably a file, but neither of those are actual requirements.

    Does this mean I should just have the foreach loop in the webpage itself and build the option elements right there? This would mean I can avoid having a view class file at all, the view would simply be the webpage.

  5. Currently I have a page where a select element resides and it shows a list of all users in the system. Here is my logic for populating the select box:

     

    1. That page makes a call to the view to be populated.

    2. The view runs a foreach loop and builds a string containing a lot of options elements holding the user names, then returns the long string back to the page to be displayed.

    3. The foreach from the view makes a call to the controller to get all the names.

    4. The controller passes the request straight through to the model.

    5. The model gets all the names from the database, adds them to an array and returns them back to the controller.

    6. The controller passes them back to the view.

    7. The view iterates through them and builds the list (in step 2 above).

    8. Element with all options is displayed on page.

     

    I'm confused if the view is for building objects which contain HTML coding, or if the view is the actual webpage being displayed, and the building should be handed off to the controller. Basically I'm wondering if the view should be pages or classes.

  6. I upgraded my server to Ubuntu 16.04 which also installed MySQL 5.7 with it and now every time I run an insert statement, it errors and tells me there is no default data specified for that column. If I go into PHPMyAdmin and specify default data for all columns, the insert will run without error.

     

    How do I turn this off? It's affecting my production sites, I just want it to go back the way it was of inserting empty strings or zeroes (or null) for any column I don't specify.

  7. I have an Amazon web server which I host maybe 5 websites on and one of them is a portal I'm building for a client. Everything works great except when I load a page that uses JavaScript files, the console complains that it can't find any of the files, so therefore none of the JavaScript code on the page works. Here is a comprehensive list of things I have tried:

     

    1. I put a test.html file in the JavaScript directory and tried to load it in my browser. My browser told me it didn't exist, 404 error.

    2. I created a javascript2 folder and put the test.html file in there, it loaded no problem.

    3. I moved all of my JavaScript files out into the javascript2 folder and changed all the reference links in the HTML to point to the new folder. The page and all JavaScript functions worked perfectly.

    4. I did a "locate .htaccess" on my server (Linux) and it didn't return anything inside the /var/www/X directory for the website. There were 1 or 2 inside some other /var/www/X2 or /var/www/X3 directories but none of them specified anything for a javascript directory.

    5. I restarted Apache2 and restarted the server many times.

    6. When I visit X/javascript/test.html in my browser, watch it fail, then check my Apache2 logs, nothing was added.

     

    For some reason my web server can find every file except for anything inside that javascript directory, I have no idea why.

  8. I have a job management portal which I built and it allows my client to create PDF files of quotes for their customers. They send their customer a link (token based URL) so their customers can click the link and view the quote. I want to serve up the PDF file on screen for their customer to view, how can I do this? Each time I attempt it, Chrome asks me if I would like to download the file. I just want to view it without the customer having a direct link to it.

  9. Great ideas, guys, I'm going to do this for sure, the other added benefit of your suggestions is that Google can no longer spider the PDF and show them to anyone Googling a name. I think I already avoided this with my robots.txt but it has been a problem in the past.

     

    I think I will still move the PDF folder outside the web directory just to make it easier to roll out updates, I no longer have to skip the PDF folder when moving all folders into production. I can just use a symlink to get the same functionality or just serve it up with PHP like someone suggested.

  10. I have a portal system I built that allows users to generate a quote PDF and save it onto the server so they can send the link to a customer for review. Is it common practice to leave the PDF directory web accessible or should it be one level above the web directory? These quotes do need to be viewed by the public since the salesmen simply send the URL to the customer for review but I've seen it done both ways. Thanks.

  11. That's odd, I wrote some quick sample code to post here for you but my example code works. I'll have to go back and work through my code to see where the problem is with that then.

    Oh well, I'll leave the example code here for someone else in case they're looking for one.

    <html>
        <head>
            <title>TODO supply a title</title>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width">
            <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
            <script type ="text/javascript" >
                function test(element)
                {
                    alert($(element).find(":selected").text());
                }
            </script>
        </head>
        <body>
            <select onchange ="test(this);" >
                <option value ="1" >One</option>
                <option value ="2" >Two</option>
            </select>
        </body>
    </html>
    
  12. I've seen many solutions on various searches using :selected or options:selected or .text(). I've tried all of these in both JavaScript and JQuery, all of them give me the same result.

     

    When I change the selected option of a SELECT element and then run the JavaScript statement, it returns the original SELECT value before I changed it, not the current value. I've tried both .text() and .val(), both give me the same result. I realize I'm not posting the code but it's literally just a SELECT element with 20 options and some JavaScript to get the text from that element.

  13. i would say yes. i have done a lot of BOMs/estimating for industrial controls, at the $1.5M level for entire plants. you are building a bill of materials (somewhere). that bom needs the quantity of each direct item that has been added, and any follow-on/sub-items that are the result of each item, recursively down to the end of the chain. from a processing point of view, just do things once, when an input is added/deleted/changed, and only for those things that are in the bom.

     

    this approach would be the same as an onchange event in a browser or a trigger in a database. some input event occurs, the code that runs, takes the rules that have been defined for that event and applies them as needed. if a window gets added/deleted, the rules defined for that window type tell the code what and what quantity of sub-items (such as the corner molding) need to be added/deleted from the bom, any of those sub-items will have rules that tell the code what and what quantity of sub-sub-items (such as fasteners) need to be added/deleted from the bom.

     

    the array structure you have for the overallQuantities already has an array of arrays for each productId, though it looks like the code isn't using more than the first element of each array. the suggested usage of the [main_item_id] as the secondary array index, in reply #6, keeps each element in the array tied to what caused that quantity. if you change the quantity of the parent (delete a specific size window), you only have to calculate and update that corresponding one element for the child item (corner molding.) all the other quantities of that particular child item aren't touched.

     

    because you have more than just two levels, what i posted in reply #6 would actually be recursive, and look like the following with as many levels as needed - 

    overallQuantities[main_item_id] = quantity
    overallQuantities[sub_item_id][main_item_id] = quantity
    overallQuantities[sub_sub_item_id][sub_item_id][main_item_id] = quantity

    for the insulated vs uninsulated pricing, i would maintain two boms, one for each case. the code would calculate quantities with and without insulation and store the results in separate boms (actually, i would just use an array with a main index that indicates insulated and uninsulated branches.)

     

    for the _calc() function in my example. you can make as many different functions that you need for the different classes of rules. just call the correct one depending on the situation. in the list of rules, you can 'dynamically' call you own functions, using variable functions, by listing the function name somewhere in the rules. in my example, i am calling the ceil function using variable functions. your rule(s) could have function name, like i used, or even an array of function names that you loop over to dynamically call each function in turn.

    I'm only using the first array element of overallQuantities for most elements but like the wallMetal example I posted above, some items have more than one quantity group because there are different quantities at different lengths. Like overhead doors, you might have 3 at 10x12 and then another 5 at 12x12. So then the quantities array would have 2 elements in it.

     

    How would this work for getting the total price? If the building costs $300,000 and part of that is corner moulding, what is the new price when the quantity of corner moulding has changed? Am I keeping another array of the total prices for each product and tallying the total price of the building based on adding them all together? Then I would have to re-add them if one of the quantities change. Is that right?

     

    So now I'm trying to understand what you're doing with the BOM because I really want to implement this in the system. So let me try and walk through an example here to see if I can figure out how this works.

     

    overallQuantities[main_item_id] = quantity

    overallQuantities[sub_item_id][main_item_id] = quantity

    overallQuantities[sub_sub_item_id][sub_item_id][main_item_id] = quantity

     

    This is the example you posted, if I'm making a change which will update the quantity of corner moulding, would the corner moulding be the sub-item or main-item in this example? Going from the beginning:

    - an edit is done on the web page (building length changed)

    - AJAX function is called

    - AJAX function passes in the name of the changed element as well as the value of that element

    - corner moulding quantity requires updating based on the changed element and its value

    - overallQuantities[cornerMoulding] is updated using the huge quantity calculation assigned to corner mouldings

    - overQuantities[cornerMoulding][whiteScrews] is updated using the quantity calulation assigned to white screws which uses corner mouldings. Is that right? Did I use the main and sub items correctly there?

    - somehow the total price is updated and the new quote is displayed to the user.

     

    There are also other things on the quote which change based in some inputs. For example, if the sales guy changes the post spacing (distance between posts) from 6 feet to 4 feet, that's going to have an effect on the quantity of posts but it's also going to show up in an area at the top of the quote which states what the post spacing is. This isn't for every element, just for a couple, but post spacing is one of them. So this text would need to change to reflect the new post spacing, as well as show the new total price of the quote.

  14. didn't see this thread before.

     

    the 'correct' way of doing this is to store the pricing information in a table using the productId, the start date (or datetime) and the end (or a NULL) date (or datetime.) each time the price changes for an item, you would set the end date (or datetime) for the previous price and insert a new row with the start date (or datetime) and the new price. any query to calculate the price would use the date (or datetime) of the quote to match the correct pricing information.

     


     

    any chance that your thread about the switch/case statement taking a long time is doing a ton of database queries (in a loop) that could account for the bad performance?

    Wow, that is genius! I actually laughed when I read it because of how smart that is.

     

    Because the system gets the overall price for the quote, it goes to the database 300 times to get the prices for all the different products with 300 individual database calls to the same table. I think it might only make the calls for products with a positive quantity though, now that I think about it.

     

    EDIT - These calls are only done when the quote is saved, not on edits. I'm not concerned right now about speed of saving quotes, currently I'm focused on edits.

  15. How about a quote items reference table. Just store the quote_id, product_id and quoted_price. All of which you should have the data for when submitting the quote. Then you don't have duplicated table data with the products and you just display the quoted price later if you need to view it.

     

    Yes, that's what I'm doing, it's just 4 columns:

    - id

    - quote_id

    - product_id

    - price

     

    Then I also have to save the sales person's commission rates:

    - operations commission

    - sales commission

    - sales management commission

    - 4 or 5 other commissions

     

    Then I save the rates:

    - winter build rate (used if building in winter)

    - remote labour rate (used if building far enough away from head office)

     

    And then I save minimums

    - minimum labour (used if labour is less than the minimum)

    - minimum materials (used if materials are less than the specified minimum)

    - minimum truss price (used if total truss price isn't at least the specified minimum)

     

    These are all things required for looking back at older quotes and they all come from separate tables and get stored into separate match tables.

  16. I know of all the ways to dump it to a text file but I want to save a database table into another match table. I have web software which allows users to enter some inputs and save a create a quote for their client. At the time of the quote, all of the building products in the database have an associated price and this pricing can change at any time. When they save the quote, I want to save all 300 products and prices into another table so I can go back later and see what the prices were when that quote was done. I don't want to load a quote from a month ago and have it price based on current pricing, I want it to price using the prices from a month ago.

     

    Right now I'm simply selecting all 300 rows and dumping them into a match table with the quote ID. That's causing it to take about 30-50 seconds to save the quote, along with a couple of other tables I'm saving as well. I'd like to make the quote saving much faster, is there a faster way to get this snapshot of the database table when the quote is saved?

  17. I've been using Workbench in Ubuntu for years without any problems at all, it hasn't crashed once.

     

    Another alternative you can try is Squirrel SQL, I know that also works for Microsoft SQL databases as well. I used it on a previous Microsoft project and it worked great but I still prefer Workbench for non-Microsoft databases.

  18.  

    we understand what you are doing and how you are doing it. the problem is, your current code is taking a long time to run and all the hard-coded logic and hard-code properties in the code are a maintenance problem.

     

    from what i gather, to recalculate the bom/price, upon each change being input, you are currently calling the code for every possible building productId (~300 times), to get each id to calculate how much of it is needed based on the quantity of what it is used for. this also requires that you call the code with the product id's in the proper order. for example, if you haven't called the code to update the cornerMoulding quantity yet, any product id that is used for cornerMoulding, such as fasteners, won't produce the correct quantity.

     

    this is what i would call a bottom-up approach. my suggestion earlier in the thread is a top-down approach, where each change only causes the items affected by that change to be recalculated.

     

    for the performance problem, if the function method produced acceptable performance, you would want to continue using that method.

     

    for the code maintenance problem (top-down or bottom-up approach), you need a data driven design, where you define the rules in a data structure (an array for now, a database table later) that tells the code what to do.

     

    for the information you have shown in this thread (bottom-up approach), the following pseudo/non-functional code demonstrates a data driven design -

    // define the rules that tell the code what to do
    $items = array();
    $items[] = array(threeByThreeFixedWindow,1.5); // id, individual multiplier
    $items[] = array(fourByThreeFixedWindow,1.5); // id, individual multiplier
    $items[] = array(threeFootStandardDoor,2.5); // id, individual multiplier        
    $rules[cornerMoulding] = array($items,1,'ceil'); // array of item(s), group multiplier, operator
            
    $items = array();
    $items[] = array(smokeStop,1); // id, individual multiplier
    $items[] = array(fireStop,1); // id, individual multiplier
    $rules[smokeDamper] = array($items, 3,'ceil'); // array of item(s), group multiplier, operator
        
    $items = array();
    $items[] = array(poly,1); // id, individual multiplier
    $rules[tuckTape] = array($items, 1/2000, 'ceil'); // array of item(s), group multiplier, operator
    // a function that knows how to apply the rules
    function _calc($rule){
        $qty = 0;
        foreach($rule[0] as $item){
            $qty += $this->getTotalQuantityBuildingProduct($item[0], $showInsulation, $showPerma) * $item[1]; // get the total for the productId and apply the individual multiplier
        }
        $qty *= $rule[1]; // apply group multiplier
        if($rule[2] == ''){
            return $qty;
        } else {
            return $rule[2]($qty); // use variable functions to apply the operator
        }
    }
    // example usage -
    $quantities[] = _calc($rules[smokeDamper]); // call this to use the defined $rules for the productId, instead of the hard-code program logic
    

     

     

    I don't know how to split your quote so I'll answer it in 2 parts here.

    As per your question in the first part, you're close but it doesn't quite work like that. I'm not updating quantities anywhere, I'm dynamically calculating the quantities each time they're requested. Let's use the following example:

    - quantityScrews = buildingWidth * 2;

    - quantity2x4 = quantityScrews / 3;

    - quantitySoffit = (quantityScrews > 100 ? quantity2x4 * 5 : quantityScrews + 4;

     

    So when a change is made in the program, I request the quantity of screws and it gets stored into the overallQuantities array for no other reason but to speed up the subsequent requests. That array isn't a master quantity array, it's just a quicker place to get the quantity instead of having to recalculate it again. So when I request the quantity of 2x4, it'll get quantityScrews from the overallQuantities array which (I assume) is faster than recalculating it again. I could be wrong but it sounds like you think I'm using that array as a quantity storage, then updating the quantities in there as needed, that's not the case. Should I be?

    The main calculation happening here is getFinalCost() which makes a request to get the total costs of all the individual products which makes a request to get all the quantities of each product. Those quantities are requested from the switch statement every time.

     

    On to the second part of your reply, the code you posted. I think you may really be on to something here but I don't quite understand it well enough to implement it. So let's say the sales guy changes the building to be 10 feet wider, the building width is used as a calculation in around 50% of the product quantity calculations so that's going to have a huge effect on the quantities of everything. More lumber, more posts, more metal, trims, insulation, everything. Also, you don't always have simple operators being applied, sometimes you have complicated IF statements like the quantitySoffit calculations above. Will that still work in your example? It looks like what you posted may work so I'd really like to understand it a bit better, please let me know if this is correct:

    - I would create a set of rules for all 300 products like you did for the 3 you posted above.

    - Then when the building length is changed, I would call the _calc method? Is that right?

    - What is the $rule variable I pass into _calc?

     

    I really like your top down idea but here are 2 more quantity calculations which I can't quite figure out how to convert to your example:

     

    This one is for interiorJTrim, it isn't too bad. There is an IF statement to see if the building is insulated because they're only used on insulated buildings. The $showInsulation variable is used to force an insulated price, I use that to get the price of the building if it were to be insulated, that allows the sales guys to print a cost on the quote for upgrading to an insulated building should the customer change their mind later. I can use that to query an insulated cost of their building by passing that value as true. You'll notice I changed all the product variables to constants but it didn't speed anything up.

                        case (self::interiorJTrim) :
                            $quantity = 0;
    
                            if ($this->isInsulated() || $showInsulation)
                            {
                                $quantity +=
                                    $this->getTotalQuantityManDoors($showInsulation, $showPerma) * 2.5 +
                                    $this->getTotalQuantityBuildingProduct(self::threeByThreeFixedWindow, $showInsulation, $showPerma) * 1.5 +
                                    $this->getTotalQuantityBuildingProduct(self::fourByThreeFixedWindow, $showInsulation, $showPerma) * 1.5 +
                                    $this->getTotalQuantityBuildingProduct(self::threeByThreeSlidingWindow, $showInsulation, $showPerma) * 2 +
                                    $this->getTotalQuantityBuildingProduct(self::fourByThreeSlidingWindow, $showInsulation, $showPerma) * 2 +
                                    $this->getQuantityCustomWindows() * 3 +
                                    $this->getTotalOverheadDoorQuantity() * 2 +
                                    $this->getTotalHeightBuildingProduct(self::biFoldDoor, $showInsulation, $showPerma) * 2 / 9 +
                                    $this->getTotalWidthBuildingProduct(self::biFoldDoor, $showInsulation, $showPerma) / 9 +
                                    $this->getTotalQuantityBuildingProduct(self::highLiftCharge, $showInsulation, $showPerma) * 1 +
                                    $this->getTotalQuantityBuildingProduct(self::atticHatch, $showInsulation, $showPerma) * 2;
                            }
    
                            $quantities[] = ceil($quantity);
                            break;
    

    Now for the worst one, this is the quantity of wallMetal, it's probably the most complicated quantity calculation in the system:

     

    - First get a value based on all the overhead, sliding and bi-fold doors the sales guy added.

    - Then if it doesn't have exterior wall light, add more to the value.

    - Then generate a quantity of wall metal by REMOVING the value we just calculated because we need to remove any wall metal which will no longer be in the places of doors and wall light. Obviously those holes in the wall will now be filled with doors and wall light instead of wall metal. We don't want to charge the customer for that wall metal if we're not using it.

    - Then we calculate another quantity to add to the quantity array. The reason we're separating the quantities is because this quantity group of wall metal will have a different length. It's the same product in the system (wall metal) but when it gets printed out on the product list for the building construction, we need to know how many pieces of wall metal we have for each length. That length is calculated separately in the getLengthBuildingProduct method which is another switch statement.

                        case (self::wallMetal) :
                            $quantity = 0;
                            $value = 0;
    
                            for ($i = 0; $i < count(explode(",", $this->overheadQuantities, -1)); $i++)
                                if (!$this->hasExteriorWallLight()) // does not have wall light
                                    $value += (floor($this->getOverheadDoorWidths($i) / 3) - 2) * $this->getOverheadDoorQuantities($i);
    
                            for ($i = 0; $i < count(explode(",", $this->slidingQuantities, -1)); $i++)
                                if (!$this->hasExteriorWallLight()) // does not have wall light
                                    $value += (floor($this->getSlidingDoorWidths($i) / 3) - 2) * $this->getSlidingDoorQuantities($i);
    
                            for ($i = 0; $i < count(explode(",", $this->biFoldQuantities, -1)); $i++)
                                if (!$this->hasExteriorWallLight()) // does not have wall light
                                    $value += (floor($this->getBiFoldDoorWidths($i) / 3) - 2) * $this->getBiFoldDoorQuantities($i);
    
                            if (!$this->hasExteriorWallLight()) // if it doesn't have exterior wall light
                                $value += $this->getTotalQuantityBuildingProduct(self::eveAccent, $showInsulation, $showPerma) + $this->getTotalQuantityBuildingProduct(self::gableAccent, $showInsulation, $showPerma);
    
                            $quantities[] = (ceil($this->getBuildingWidth() / 3) + ceil($this->getBuildingLength() / 3)) * 2 + 1 - floor($this->getLengthExteriorWallLight() / 3) - $value;
                            
                            $quantity = 0;
                            $value = 0;
    
                            for ($i = 0; $i < count(explode(",", $this->overheadQuantities, -1)); $i++)
                                if ($this->hasExteriorWallLight()) // has wall light
                                    $value += (floor($this->getOverheadDoorWidths($i) / 3) - 2) * $this->getOverheadDoorQuantities($i);
    
                            for ($i = 0; $i < count(explode(",", $this->slidingQuantities, -1)); $i++)
                                if ($this->hasExteriorWallLight()) // has wall light
                                    $value += (floor($this->getSlidingDoorWidths($i) / 3) - 2) * $this->getSlidingDoorQuantities($i);
    
                            for ($i = 0; $i < count(explode(",", $this->biFoldQuantities, -1)); $i++)
                                if ($this->hasExteriorWallLight()) // has wall light
                                    $value += (floor($this->getBiFoldDoorWidths($i) / 3) - 2) * $this->getBiFoldDoorQuantities($i);
    
                            $quantity += $this->getQuantityExteriorWallLight() - $value;
    
                            $quantityGableAccents = $this->getQuantityBuildingProduct(self::gableAccent, $showInsulation, $showPerma);
                            
                            if ($this->hasExteriorWallLight()) // if it has exterior wall light
                                $quantity -= $this->getTotalQuantityBuildingProduct(self::eveAccent, $showInsulation, $showPerma) + $quantityGableAccents[0];
    
                            $quantities[] = $quantity;
                            break;
    
  19. i've been looking at your code posted in this thread, and it appears that the rules in the code are for calculating the amount of a sub-item by getting the quantity of each relevant main item that uses that sub-item and putting that quantity through the rule in this code. also, despite storing the quantity for each productId as an array within the main array, the code in this thread is only storing ONE array element, with the total quantity.

     

    this means you are calling the getQuantityBuildingProduct() function for each sub-item that a main item uses, each time the main item quantity gets changed (unless you are calling the function for EVERY POSSIBLE sub-item, every time ANY main item quantity changes, in which case i can see why this would take 10 seconds). this requires that the code (or data) for each main item contain a list of sub-items and your code in this thread requires the correct rule for each sub-item.  so, you have two separate places in the code that must be kept up to date with any new or changed relationship between main and sub-items.

     

    i suggest, instead, just using the list of sub-items, located in the main item code (or data), to call the appropriate rule for each sub-item and update the sub-item quantity at the time you update a main item quantity.

     

    you are storing data like this -

    overallQuantities[main_item_id][] = quantity // main items
    overallQuantities[sub_item_id][] = quantity // sub items

    if you add the main_item_id as an array index for the sub-items, you can find and update the corresponding quantity of a sub-item when the quantity of the main item changes -

    overallQuantities[sub_item_id][main_item_id] = quantity

    for example -

    overallQuantities[cornerMoulding][threeByThreeFixedWindow] = x quantity
    overallQuantities[cornerMoulding][threeFootStandardDoor] = y quantity

    your getTotalQuantityBuildingProduct() function will work with this structure (it's actually getting a single element array now, but would be getting an array of arrays, if a sub-item is used with more than one main item.)  you can also replace the foreach() loop in the getTotalQuantityBuildingProduct() function with an array_sum() call, both with your current scheme and with the one i have suggested.

     

    this will also allow you to produce a cross-reference listing of the sub-items showing what amount of them are used for each different main item -

    cornerMoulding -
        threeByThreeFixedWindow - x quantity
        threeFootStandardDoor - y quantity

    edit: and in thinking about your use of the $this->overallQuantities[$productId] array to cache the amounts, if you change a quantity of a main item, i.e. the number of a type of window, your code won't recalculate the amount of a sub-item, i.e. the corner molding, if the sub-item amount is already in the array, which it likely would be, unless you have even more code that we haven't seen to take care of this common occrance.

     

    As far as I can understand what you're saying, I may have explained it incorrectly. The quote page has about 60 different inputs for changing things like:

    - building width

    - building height

    - building length

    - building type (residential, commercial, barn, hayshed....)

    - insulated or not

    - how many windows?

    - how many doors?

    - what's the roof pitch?

     

    The sales guy will sit down with a customer and enter in all that information and right next to the input boxes there is a live quote which displays the actual live price for those options. That price is calculated by running through the quantities of every single available building product (300 of them), getting the unit price and finally getting a final cost for that job, down to the penny. It's so accurate that I know that building will require 14,394 screws to complete, not 1 more, not 1 fewer. So I don't think I can do it your way (please tell me if I'm wrong) because I don't have parent items and sub-items, I just have inputs. If the sales guy makes the building 10 feet longer, the program needs to recalculate every quantity because that might change the quantities, lengths, widths and heights of 20-30 different items (lumbers, metals, trims, posts, more labour.....). So they're not just choosing to add more corner mouldings, they're changing the building dimensions and that is getting a new quantity for corner mouldings on the back end.

  20. Is it the same amount of time for stuff at the top of the switch (corner moulding) than at the bottom (ceiling-only labor)?

     

     

    Every time an input box is edited on the quote page, the pricing for the entire job is recalculated, that means recalculating every quantity of every product, building the HTML for the quote and displaying it on the page using AJAX. So if the customer wants 10 gable stops instead of 5, you make that change and the program recalculates every single quantity of every product, every length, height, width, recalculates the cost of that job and displays it. It's taking about 10 seconds where before it was almost instant with individual functions for each call. I'm actually getting complains from the sales guys that it's taking so long to update now after a change.

    So to answer your question, there is no time when I would only be calling corner moulding or ceiling-only labour, every single building product is recalculated and called on any edit. When the sales guys are sitting with a customer, the customer likes to change 10-20 different things to try and get the price within their range. They might add a window and that will change the quantities of 5 or 6 different lumber products used in framing the window, it'll remove quantities of exterior metal and add window labour costs so the entire building needs to be recalculated when this change is made.

     

     

    what was the performance of your code when using functions (i'll assume you were calling the appropriate function dynamically using variable functions?)?

     

    using a class->property as the case x: value, is not going to be as efficient as using a fixed value. i would use a defined constant as the case values. the same would be true for all the other class->properties you are showing in the code. you have essentially created a different variable/property, who's name indicates the purpose of the variable, when in fact nothing about the usage is variable.

     

    No, I was not using variable functions, that was the reason for the change. I had actual functions created and named for every single item quantity, width, length, height, unit-price and total price. It was a huge pain adding a new product and entering functions for every dimension calculation, then adding that to the total price of the building price calculation. That's a good idea to change all the items to constants though, I'll try doing that. Right now I have all the building products in the database with a row ID and then defined in the program like so:

            private $lumber2x8x12Treated = 14;
    	private $lumber2x8x16Treated = 15;
    	private $lumber2x6x12 = 16;
    	private $lumber2x6x16 = 17;
    	private $lumber2x8x12 = 18;
    	private $lumber2x8x16 = 19;
    	private $lumber2x4x12 = 20;
    	private $lumber2x4x16 = 21;
    	private $lumber2x10x16 = 23;
    	private $lumber2x6x16TreatedFillerBoard = 24;
    	private $lumber2x6x12TreatedFillerBoard = 25;
    	private $lumber2x8x16TreatedFillerBoard = 26;
    	private $lumber2x8x12TreatedFillerBoard = 27;
    	private $lumber2x6x12Treated = 32;
    	private $lumber2x6x16Treated = 33;
    	private $wallMetal = 34;
    	private $gableMetal = 42;
    	private $roofMetal = 43;
    	private $wallScrews = 44;
    	private $trimScrews = 46;
    	private $heelMetal = 47;
    	private $biFoldDoorMetal = 48;
    	private $slidingDoorMetal = 49;
    	private $exteriorBaseTrim = 50;
    	private $birdStop = 51;
    	private $ridgeCap = 52;
    	private $ridgeLight = 53;
    

    As for the post right above this one, I'll reply to that once I read it again and figure it out a bit better, I just ran through it quickly but I'm heading to bed here and need some more time to read through it a bit better. I will reply to it when I get a chance.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.