426

(10 replies, posted in General)

Adam, I had a little bit of time to look at your project and make modifications to incorporate refunds. I think I have all your basis covered. Check it out and let me know. Sorry for all the script code. It was necessary in order to maintain accurate stock levels and to keep transaction integrity between invoices and the respective refunds of invoices. I rearranged the procedures so all are grouped with their respective forms and I put comments in so hopefully you will be able to follow the logic of the code.


I kept all quantities as positive numbers. I handled the refunds mathematically within the script. Also, I removed the "Add New Product" button from the Sale Invoice form. Logically speaking, it does not make sense to add a new product when doing a sale transaction because you need to purchase some before you sell some.


Since the "Add New Product" is only on the Purchase Invoice form, I moved all the validity checking on the purchase form to a pre-Save procedure and if it passes the checks, then it clicks the real save button. At this point I did not add another qty field on the Purchase Invoice form. I don't think you actually need it, but you may have a reason for it.

427

(10 replies, posted in General)

Field names in a script are part of the form property, such as in your case "frmsaleInv.edSaleInvQty.text". Where I have Qty by itself, with nothing around it, is a variable.


I had that new sale invoice situation covered, but I must have inadvertently removed the check. Anyway, change your "If" statement to the following. You do not need the other parts of the "If" statement. In fact, it will never be true on a "NewRecord" action.


If frmSaleInv.dbAction = 'NewRecord' then

Also change

If CurrQtyVAR - Qty <= 0 then

To

If CurrQtyVAR - Qty < 0 then

428

(10 replies, posted in General)

Yes you're right, it can get rather complex for anybody when building inventory control systems or supply chain systems.


Sometimes I get a little lax on naming conventions. You absolutely should have a methodology in naming conventions. It definitely helps later when you have to come back to make changes or enhancements to the project. Don't look at that as a shortcoming. It's very essential.


During renaming variables, changing  var Init_Qty to InitialQtyVAR returns "Undeclared identifier" around //...(frmSaleInv.InitialQtyVAR.Text);// 


In the case of Init_Qty, I called a variable that name and I also called the form field that name. Sorry for the confusion. So for the frmSaleInv field name you should change it to your naming convention of "edInitQty" not InitialQtyVAR.  It should be frmSaleInv.edInitQty.text.  Hope this helps.

429

(10 replies, posted in General)

Adam, An update to the project. I missed a scenario where the stock level could go below zero. I have the fix below.


Replace procedure Form1_Button9_OnClick.

With

procedure Form1_Button9_OnClick (Sender: string; var Cancel: boolean);
var
  Curr_Qty: Integer;
begin
    Adj_Qty := SqlExecute('Select Qty From PurchInv Where Id = ' + Form1.tgMainPurchInv.sqlValue);
    Prod_Id := SqlExecute('Select id_Product From PurchInv Where Id = ' + Form1.tgMainPurchInv.sqlValue);
    Curr_Qty := SqlExecute('Select Qty From Product Where id = ' + IntToStr(Prod_Id));
    If Curr_Qty - Adj_Qty < 0 then
      Begin
        MessageBox('Deleting this purchase invoice will cause the stock level to go below zero.','Error',MB_OK+MB_ICONERROR);
        Cancel := True;
        Exit;
      End;
end;

This will take care of the situation where for instance you have a stock level on an item of zero and then you add a purchase invoice for 5 which would increase the stock level to 5 and then you add a sales invoice of 1.  Ordinarily you can delete a purchase invoice and it will adjust the stock level for you. However, in this situation it would cause the stock level to go below zero if you deleted the purchase invoice because you have sales against the item.

430

(10 replies, posted in General)

Adam, this type of updating another table can be tricky and involved because there are various situations you have to account for when processing data in the respective update forms, particularly when adjusting quantities and products simultaneously. This is not a criticism, but I believe your approach will not work. I put together the coding necessary to update stock levels. It manages the integrity of the stock levels so input mistakes will not cause stock levels to go below zero. Test out various situations to make sure I covered everything. I used the project from your first post, not your most recent one.

431

(6 replies, posted in General)

Adam, Maybe the attached is what you want. It's a little different approach, but it creates new refund records based on the sale or purchase invoice records. To issue a refund, select the row you want to refund and click on the issue refund button on Form1. You can only refund on "Sale" or "Purchase" rows in the respective grids. Once you are in the update form, you can't change the DbCr field. In fact the DbCr field will always be populated based on the button you press in Form1.


You have a lot of buttons going on in the frmInvoice form. I didn't do anything with them or any of your script. Didn't want to mess up anything you were applying with any of that.

432

(4 replies, posted in General)

I think the following will take care of your situation.

In your SelectFromDeliverableDB_Button1_OnClick procedure replace the following line

SchedulingDB.StudentNameDB.dbItemID := SelectFromDeliverableDB.TableGrid1.dbItemID;

With

SchedulingDB.StudentNameDB.dbItemID := SqlExecute('Select id_AddCourses From DeliverablesDB Where Id = ' + SelectFromDeliverableDB.TableGrid1.sqlvalue);

433

(4 replies, posted in General)

You forgot to include the StudentNameDB combobox in your Save button action.

434

(5 replies, posted in General)

Not a stupid question. If I'm understanding your question correctly, probably the quickest and easiest solution would be to utilize a product such as SqliteStudio and use the export/import features.

435

(6 replies, posted in General)

Just place the following in your DB/CR combo. That should take care of that situation.

procedure frmSalesInv_cbSaleInvDBCR_OnChange (Sender: string); // SALE or REFUND
begin
  If frmSalesInv.cbSaleInvDBCR.dbItemID = 1 then
    Begin
     If frmSalesInv.edSalesInvDelivCost.Value < 0 then
      frmSalesInv.edSalesInvDelivCost.Value := 0 - frmSalesInv.edSalesInvDelivCost.Value;
     If frmSalesInv.edSalesInvDiscount.Value < 0 then
      frmSalesInv.edSalesInvDiscount.Value := 0 - frmSalesInv.edSalesInvDiscount.value;
    End;
  If frmSalesInv.cbSaleInvDBCR.dbItemID = 2 then
    Begin
     If frmSalesInv.edSalesInvDelivCost.Value > 0 then
      frmSalesInv.edSalesInvDelivCost.Value := 0 - frmSalesInv.edSalesInvDelivCost.Value;
     If frmSalesInv.edSalesInvDiscount.Value > 0 then
      frmSalesInv.edSalesInvDiscount.Value := 0 - frmSalesInv.edSalesInvDiscount.value;
    End;;
  CalculateTotal;
end;

436

(6 replies, posted in General)

Check this out and see if it's ok for you.

437

(3 replies, posted in General)

Fixed.

Kim,
I see that nobody has responded yet on your issues with parent-child relationships. I don't know if you still need help, but thought I would share some info on this topic using your project and hopefully I'm understanding your dilemma. I welcome others to provide input as well. I hope I don't confuse you. I apologize in advance if I do. I also apologize for the length of this post. Parent-child concept is not always the easiest no matter what the development environment is. I'll start by saying that Parent-Child record relationship does work in MVD. It's just a matter of how you want it to specifically work. Just a word of caution, it is not all automatic as one may think. Some things are automatic and others are not. Most of the time it will probably require some scripting to do exactly what you want, but not a lot and mainly minor in nature. In general terms using your parent-child scenario, you can place Table 1 and Table 2 fields on the Table 3 form, but you can only update Table 3 fields on that form using the normal MVD Save action. The other fields can only be displayed (disabled fields or set as label captions). Even if you do not disable the fields, they won't update upon save. Here are the answers to your questions.


Question 1 - Yes the parent id is stored on the child table as an integer.


Question 2 - Yes and no. I'm not exactly sure what you mean by "call all the fields from Tabone". The tabtwo.id_tabone field is only a link field with the parent id. It is typically used in a combobox on a child form and it retrieves a single text field from the parent table (in your case from Tabone). That's all it does. It does not do anything with bringing in the date field from tabone. But you can still display the date field on a child form. In your case, If you want to display the date from Table 1 onto Table 3 form, it will require a line of script.


Question 3 - Again I'm not exactly sure what you mean by "call all the fields". Probably the best way to explain how to display Table 1 and Table 2 fields on Table 3 form is to illustrate it with the following image. It is different between "ShowRecord" action and "NewRecord" action and some fields are not automatic.


The following image is a result of "ShowRecord" action from Tablegrid4 edit on Form1. No script was used for Tabthree form. Fields from Table 3 and Table 2 are shown automatically, but not Table 1 fields and the Type table text field. It requires script to retrieve that data.


https://s10.postimg.org/tpd06zfs9/Show_Record_Tab3_Fields.jpgimg host


The following image is a result of "NewRecord" action from Tablegrid4 add on Form1. Again this image shows Tabthree form with no script. MVD clears all fields, including Table 2 and Table 1 fields. Therefore a script needs to be applied to bring in those fields.


https://s13.postimg.org/n989m8p8n/New_Record_Tab3_Fields.jpg


The attached project mimmicks the images above except that fields are filled where necessary with script. I hope this helps. Again, if anyone else has anything to offer to help Kim in understanding this within MVD, please do so.

Kim,

Derek is right. Typically through normal MVD actions, you would have a separate update form for each table (tablegrid) and usually they are on their own chain of forms. Having all the tablegrids on one form is fine, but it requires just a little bit of minor scripting to keep them in sync.


The update forms are only to update the table record that the tablegrid is focused on. Usually in a child form there is a combobox to maintain the relationship to the parent, which you correctly have defined. On a child form, If you want to bring in fields from a parent or grandparent table besides the parent combobox, this usually needs a little bit of scripting. You would define these fields either as labels or disabled input fields and then bring in the data from the parent/grandparent tablegrid or directly from the parent/grand parent table through SQLExecute. I revised your project just a little bit to show you. You were actually on the right track. You just can't update more than the record from the tablegrid. Now having said this, with scripting you can do almost anything. So if you wanted to update other tables simultaneously, it would require scripting to accommodate.

440

(14 replies, posted in General)

That's not the default checkbox. The following checkbox should be checked.
https://s14.postimg.org/4idsfeze9/Check_Box_Default.jpgimage hostingcertificity.com


In the attached project the default checkboxes are checked. Also the checkboxes validation was corrected.


The reason for the auto save is because in order to save the child records (generated passwords) the main record needs to be saved for NEW main records (password set in your case). But in my project the user does not know that it was saved. So, for instance, if the user wants to add a new set and generates the passwords and then decides they want to cancel, then the cancel button will remove the password records and the main record and everything is back to where it was before the new password set was requested.  Even on password sets that exists, if you click the generate button and then decide not to save them, the cancel button will remove the newly generated passwords. In other words, the save and cancel buttons to the end user function just like normal. Try it out. You'll see what I mean.

441

(14 replies, posted in General)

Since you had two save buttons on the form, I didn't know if you had something special planned for them. You can remove the dummy save button and replace line 89 in the script with

frmPwGen.Button3.Click;

The default state set to true for the checkbox properties works on my end. Script is not doing anything with the checkbox properties. Keep in mind that the default state is only for new record state (in your case a new set).

442

(14 replies, posted in General)

Adam,  see if the attached gets you closer. I changed the design slightly. Instead of having a finite number of Password and Used fields, I created a child table and used a tablegrid to maintain the generated passwords. This way you are not limited to 10 passwords. It required some extra coding for updating and canceling updates on one form, but you are not restricted to the number of generated passwords. The "Generate Passwords" button will generate the number of passwords based on the Quantity field on the form and display in the tablegrid. It's an editable grid so you can type in the Used fields directly in the grid.


I'm not sure why you have options for the properties of the password. I would think that you would want the strongest password with all the properties present, but not really knowing what this project will eventually be used for, I went ahead and accommodated for the various choices. The only option I did not account for was the "No similar characters". I wasn't exactly sure what that meant and what the algorithm would be. You can add to or remove from the punctuations(symbols) allowed by changing the string called "Punctuation" in the script.


Hopefully this helps.

443

(14 replies, posted in General)

Thought I would take a stab at it.

444

(48 replies, posted in General)

You are right about the memo field. I wasn't sure if that was a DB field or a label and just  made the assumption it was a DB field. I meant to stipulate that in my post, but glad you figured it out. Good luck on the rest of your project.

445

(48 replies, posted in General)

You had several errors in your code. Also, text fields are padded with spaces in FastReport so they need to be trimmed in If statements. Try below.


if trim(ReportDbCrdbcr.text) = 'Sale' then
  begin              
    ReportDbCrdbcr.font.Color := clBlue;
    ReportMemo1.font.color := clBlue;
  end else    
    begin
     ReportDbCrdbcr.font.Color := clRed;
     ReportMemo1.font.color := clRed;
    end;

The function is SQLDateTimeToDateTime (). Place as part of combobox onChange event.


procedure Form1_ComboBox1_OnChange (Sender: string);
begin
    Form1.DateTimePicker1.DateTime := SQLDateTimeToDateTime (sqlexecute('select _date from date where item =' + '''' + form1.ComboBox1.Text + ''''));
end;

447

(8 replies, posted in General)

Kim,  I made an attempt to put together something you are looking for. I used your project in a prior post. I didn't realize that you had an updated project. So hopefully I'm not way off. But if I am, maybe you can use parts of what I put together. The one thing I would caution you on is the freeform style of the ranges. Since your ranges usually have spaces around the dash, the script is counting on that format. Obviously one can program around that, but I didn't have any more time to spend on it for now. Check out the attached project and see if you can use any of it.

448

(8 replies, posted in General)

Kim,  to format your values in the grid out to 4 decimal places, create an onChange event for your tablegrid1 and place the following formatmask statement:


procedure Form1_TableGrid1_OnChange (Sender: string);
begin
    TNxNumberColumn(Form1.TableGrid1.Columns[1]).FormatMask := '#0.0000';
end;

Question - do your ranges need to be stored in one field? Can they be split into two fields?


Derek or Dimitry - chime in anytime. I don't want to step on any toes and my time is somewhat limited, but I'll do what I can.

449

(5 replies, posted in General)

tcoton,  I put together a very simple project to demonstrate the use. The project is actually two apps, Send Parm app and Receive Parm app. After extracting the project go into the Send Parm folder and you'll see the Receive Parm folder. Run the Receive Parm app first. This will create the exe program the first time. Close the Receive_Parm program. Then go back to the Send Parm folder and run the Send_Parm app. Enter some text in the text box and click on the Run Program button. The Receive_Parm program will open and display the parameter you entered in the sending program textbox.

450

(5 replies, posted in General)

Thank you Dimitry. Much appreciated.