Re-order id after deleting a content in drupal 8 - drupal

I am new to Drupal and I came to a scenario where i have created an auto-incremented "order no" and its working correctly, but on deleting a content data, the "order no" field is not re-ordering. (client requirement)
For Example:
some data1
some data2
some data3
if I delete 2, the new order should be:
some data1
some data3
Any help will be much appreciated.

You can achieve this by write custom hook or rules module, whenever delete node hook trigger, update auto_increment value with previous one for all nodes from deleted node using node update hook as well as update last auto_increment value in specific table for next node creation. You can also do by query update in table. But you have to check carefully which are tables involved.

Related

How to programmatically link newly created records to a record from another table

Thanks in advance for your advice!
Background
I’m creating a database to track orders placed by customers.
An ‘Orders’ table stores general details about an order like the customer’s name, order date, and delivery-required date.
A separate ‘Order_Items’ table stores the specific items that the customer has ordered.
The is a one-to-many relationship between the ‘Orders’ table and ‘Order_Items’ table, i.e. one ‘Order’ can have many ‘Order_Items’, but each ‘Order_Item’ must be associated with only one ‘Order’.
Current State
Currently, I have a page where the user creates a new ‘Order’ record. The user is then taken to another page where they can create as many ‘Order_Item’ records as are needed for the order.
Desired State
What I would like to achieve is: When a user creates new ‘Order_Item’ records, it automatically allocates the current ‘Order’ record as the foreign key for the new ‘Order_Item’ record.
What I've Tried So Far
Manual Action By The User: One way of establishing the link between an 'Order' and all of its 'Order_Items' would be to add a drop-down widget which which effectively asks the user something like "Which order number do all of these items belong to"? The user's action would then establish the link between the two tables and associate one 'Order' with many 'Order_Items'. However, my goal is for this step to be handled programatically instead.
Official Documentation: I’ve referred to the offical documentation which was useful, but as I'm still learning I don’t really know exactly what to search for. The prefetch feature appeared promising but does not actually establish a link; it just loads associated records more efficiently.
App Maker Tutorials: I found an App Maker tutorial which creates an HR App where a user can create a list of ‘Departments’, then create a list of ‘Employees’, and then link an ‘Employee’ to a ‘Department’. However, in the example app this connection is established manually by the user. In my desired state I would like the link to be established programatically.
Manual Save Mode:
I’ve also tried switching to manual save mode so that the user has to create a draft ‘Orders’ record and then several draft ‘Order Items’ records and then save them all at once. However, I haven’t managed to make this work. I’m not sure whether the failure of this approach is because 1) I’m try to create draft records on more than one table, 2) I’m just not doing it correctly, or 3) I thought I read somewhere that draft records are deprecated.
Other Ideas
I'm very new to this field and am may be wrong, but I have a feeling I may need to use some scripting to establish the link. For example, maybe I could use a global variable to remember which 'Order' the user creates. Then, for each 'Order_Item' I could use the onBeforeCreate event to trigger a script that establishes the link between the 'Order_Item' and the 'Order' that was remembered from the previously established global variable.
Updated Question
Thanks Markus and Morfinismo for your answers. I have been using both answers with some success.
Morfinismo: I've successfully used the code you directed me to on existing records but cannot seem to get it to work for newly created records.
For example:
widget.datasource.createItem(); // This creates a new record
var managerRecord = app.datasources.Manager.item; // This sets the Manager of the currently selected parent record as a variable successfully.
var teamRecord = app.datasources.Teams.item; // This attempts to set the Manager of the currently selected record as a variable. However, the record that was created in line 1 is not selected. Therefore, App Maker does not seem to know which record this line of code relates to and returns the error Cannot set property ‘Manager’ of null.
// Assign the manager to the team.
teamRecord.Manager = managerRecord; // This successfully assigns the manager but only in cases where the previous line of code was successful (i.e. existing records and not newly created ones).
Do you have any suggestions or comments on how to apply this code to records that are created by the initial line of code in line 1?
I have found the easiest way to create related items for situations such as yours is to actually import a form with the datasource set to Parent: Child (relation) or Parent: Child (relation) (create). So in your case the datasource would need to be set to Order: Order_Items (relation).
You can get this accomplished in two different ways using the form widget wizard:
Option 1:
If your page datasource is set to Order_Items, drag your form on your page.
In the datasource selection section, your datasource in the form widget should default to `Inherited: Order_Items'. Click the 'Advanced' button in the bottom left corner, then from the datasources category find Order as your datasource, then select relations in the next field, and then Order_Items in the next field, choose 'Insert only' or 'Edit' form and then the appropriate fields you want in the form.
Now every item that gets created in that form will automatically be a child record of the currently selected record in your Order datasource.
Option 2:
If your page datasource is set to Order, drag your form on your page.
In the datasource selection section, your datasource in the form widget should default to Inherited: Order. Scroll down in your datasource selection section until you find Order: Order_Items (relation), then choose 'Insert only' or 'Edit' form and then the appropriate fields you want in the form.
Now every item that gets created in that form will automatically be a child record of the currently selected record in your Order datasource.
In your Order model, make sure that the security setting is set appropriately that a user is allowed to create relations of Order_Items in Order. That is the simplest approach in my opinion since you don't have to hard code the parent into your form or client/server scripts. It is automatically based on the currently selected parent, and is essentially doing the same thing that #Morfinismo explained in the client script section.
The comment I placed under your question included a link to the official documentation that explains what you need. Anyways, your question is not clear enough to determine whether you are creating the records via client script or server script, hence this is a very general answer.
To manage relations via client script:
var managerRecord = app.datasources.Manager.item;
var teamRecord = app.datasources.Teams.item;
// Assign the manager to the team.
teamRecord.Manager = managerRecord;
// Changes are saved automatically if the datasource in auto-save mode
// Add a team member to a Manager's team.
// Note: Retrieve Members on the client before proceeding, such as by using prefetch option in datasource - datasources Team -> Members)
var engineerRecord = app.datasources.TeamMember.item;
teamRecord.Members.push(engineerRecord);
To manage relations via server script:
// Get the record for the Team to modify.
var teamRecord = app.models.Teams.getRecord("team1");
// Assign a manager to the Team.
var managerRecord = app.models.EmployeeDB.getRecord("manager1");
teamRecord.Manager = managerRecord;
// Note: The new association is not saved yet
// Assign a team member to the Team.
var engineerRecord = app.models.EmployeeDB.getRecord("engineer1");
teamRecord.Members.push(engineerRecord);
// Save both changes to the database.
app.saveRecords([teamRecord]);
The above information is taken directly from the official documentation, which like I said, I referred to in the comment I placed under your question.

Adding and removing rows from sql server table when making updates to record

I have a SQL Server table that contains two columns AppID and GroupID. The table is populated from a asp listbox. An AppID can have many GroupID's associated with it.
It works fine for adding Groups for each App and when a user wants to edit a record I can populate the Listbox with the already selected items.
What I want to know is when a user edits the items in the listbox, they can deselect existing items and select new ones what is the best way to update the table in the database? Would I be better to delete all the records for the AppID or is there a better way?
There isnt likely to be more than 12 Groups linked to anyone App.
EDIT
Sorry should have said that the table is a link table between the Apps table and the Groups table. The IDs in the link table are the primary keys from those tables.
TIA
Pro grammatically it would be easier to delete everything for the AppID and add them all back in. However your performance would take a huge hit using this method.
So your best method from a performance perspective would be to split the operation into 2 parts:
find records in your link table that are no longer in your ListBox &
delete them
find records in your ListBox that aren't in the table & insert them
This will only work well if you keep track of the data to insert and delete as the user clicks on the ListBox. Then apply the changes all together as doing the inserts & deletes one record at a time would mean many more transactions which would be slower.
EDIT
A further performance improvement would be to turn some of the deletes & inserts into updates as updates are typically faster than delete + insert. Albeit this would add complexity to your code so it comes down to what is more important.
As before keep track of the deletes & inserts as the user makes changes to the ListBox
Count how many deletes & inserts you have
Take the lowest number and that is how many delete + inserts you can convert into an update. For example, if you need to delete GroupID 123 & insert GroupID 456, then instead just update GroupID 123 to 456.
If you have left over deletes, then perform those, otherwise handle the leftover inserts

insert data in another table then update data in current table

I have two tables with the same fields : vessel_details and vessel_history. There is a form provided to the user for the renewal of the vessel license. Upon page load, all the data of the vessel will be displayed(textbox) through the form. These data are retrieved from the vessel_details table. Once the user edited the details, and clicked the update button, the original details(before the editing) from the vessel_details should be transferred in the vessel_history table before the updating of the current filled-out/edited details in the vessel_details.
upon clicking the update button, how can i insert the original details from the table vessel_details to the other table (vessel_history),and eventually update the vessel_details table with the new (edited) details?
Without knowing what technique you are using to get you data, what you can do is clone original record container which might be a DTO or dataset or something else. Again you have to decide whether is deep clone or shadow clone and on update clone goes to history table and original updates values.
You could use a trigger in the database to do this. Then no matter what technology you use at the front end it will always work.

Getting value of auto incremented column in advance

I am using the entity framework in asp .net. In the database, I have a table named Post in which id is auto incremented. Now, before adding a new post, I want to know which id will be assigned to this post.
One way for you get your goal is use a SQL Server Procedure get max id from your table post and plus 1 and you will get you next Id.. this is a waste way for get your goal
SELECT MAX(ID) FROM POST
For how using store procedures into EF read this link maybe help you
http://www.devtoolshed.com/using-stored-procedures-entity-framework-scalar-return-values

How to keep old and new version of record until a supervisor approves the changes?

I am currently working on a ASP.NET MVC 3 project in which I have to keep record of field changes with certain attributes. Example:
public class MyModel
{
public String PropertyOne { get; set; }
// Need to keep track of these properties
[RequiresSupervisorKey]
public String PropertyTwo { get; set; }
}
As soon as one of the fields is changed, it requires a supervisor to approve of these field changes.
Until the changes have been approved the record will be in a pending state, and I somehow need to keep the old record and the new record until such time!
What is the best practices regarding storing these records? Should I have 2 records in the table in the database or should i have a audit table that can store this data until it has been approved.
Thank you.
I'd save them in one table too. Use a combined key for identifying a unique row. Row ID with autoincretment id. and datetime as the second part of the combined key. When a 3rd row can store the state. This allows you versioning as well. If you select the field for display you select by id order by datetime desc where state is approved limit 1. Hope this helps ;-)
This is my .02 from other projects but I would add a version or state column to the table and keep n number of records in the table. I don't know if its possible in your system for the record to be changed by two different users with different changes, but in situations like this that is usually the case. An audit table is an acceptable solution but in general I prefer to keep things in one table.
I would keep both records in the table (old and new) with an extra field for status (such as active, pending, delete, disapproved) (or what ever statuses you think you need).
Then I would create a view that shows only the active records (used for most purposes) and one that shows only the pending records (uses for the supervisor approval page).
I would create a trigger on the table to ensure only one record was active at a time. So if a supervisor changed a record from pending to active, it would take the old record and change it to the delete status. If a supervisor disapproved a change, it would go to the disapproved status.
To keep the table nimble (you indicate no need to permanently store the old statuses), I would have a job that runs at night to delete all records in the delete or disapproved status.

Resources