Exactly what i was looking for. The way you adding the number using Creating event on the model and they way you are finding the next incremental number with max. (thumbsup)
Using max + 1 is dangerous: if you delete the latest entry and after that create a new entry, it will get the same id as the entry before. Better approach: use the ids only internal and not visible to the frontend. Instead show UUIDs on the frontend. UUIDs are also safer because you cannot guess the ids of an item. But use the integer ids internal because joining between integers is way faster than between strings (that's what UUIDs are in MySQL for example).
@@ehtashamshami6969 internal means that you only use them to build relationships between entities. But you never show them to the outer world. From the outside you use the uuids (or what I use personally: nanoids with ZBase32) to identify an entity. An yes, the "internal ids" use autoincroment to prevent collisions.
Good video! A third and intermediary option would be to have a mutator getFullNumber that executes that logic without requiring the view to do it or a field in the database. This way you can call the full_number as an attribute without the hassle of storing duplicated data.
But you always need to store all transaction data just as the same as when they were created. Imagine when the company decides to change the prefix at some time later, all invoice numbers in the past will also change, which is obviously not a good thing.
Hi, nice quick and concise. Only downside i can see to creating them on the fly and not storing ffull invoice number, is that if you update your prefix, customers previous invoices would change. Which for accounting is not ideal.
thanks for the video! you will get a a PDO error in case of creating few invoices at the same time (if you have unique key for number+series_id) or you will get few invoices with the same full number. Reason a DB query to fetch latest invoice number with current series_id takes some time and if you have few requests to create an invoice at the same time, most likely this DB query will return the same result. For big DB tables with few indices it's a pretty common problem for approaches like this. In order to avoid this problem, you can use locks or set full_number in a queue
Thanks for kind words. 1. I already have a lot of videos about Eloquent, here are search results: ruclips.net/channel/UCTuplgOBi6tJIlesIboymGAsearch?query=eloquent 2. The biggest set of information on that topic is in my course "Eloquent: Expert Level" bit.ly/eloquent-course
An important note to mention is this context is that , you need to keep tracking of the serial number of invoices , so the delete invoices could be noted , lets say that you will use soft delete option in laravel , then you has to add withTrashed() scop to Invoice::where('series_id', $model->series_id)->max('number) +1 so you can keep the serial correctly and there are no serial overlap could happened in this case.
I love your tutorials sir. I am a beginner learning laravel, I would like to request if you have a tutorial making a full working application step by step. It will help me a lot in advancing my knowledge. Thank you.
I've done a lot of live-coding in the past, like this: ruclips.net/video/Oq_b1g_JpCM/видео.html But it takes a very long time, to be honest. So maybe I will do that only in the form of a premium course, just to pay off my time spent. Would you buy something like in that playlist for, say, $19? (which is a typical price for any of my courses here - laraveldaily.teachable.com)
my creating event is never fired static::creating(function ($model) { error_log('creating'); $model->nice_number = str_pad($model->unit_number, 4, 0, STR_PAD_LEFT); }); Any ideas?
Thanks man! Is there a possibility of competition between users and the max function returns the same number when generating the invoice? If so, what can we do to avoid it?
Yes, there is a (very small) possibility of that happening. If you want to be very careful, you could use a database transaction to have it all in one go, or perform one SQL query like "insert into invoices (select max from series) ..."
easy way to use accessors and mutators laravel.com/docs/7.x/eloquent-mutators#accessors-and-mutators example: Put this in the model you want to change the id from public function getIdAttribute($value) { return str_pad($value, 5, '0', STR_PAD_LEFT); }
Great tutorial sir 👍. If you don't mind, would you sharing about how to handle multiple approval (user to manager to supervisor) with division (IT/HR/Finance). Tq so much
Can you please give more details, how it should work exactly, what is "multiple approval" or give any link to the description of other existing system.
@@PovilasKorop sorry if you got confused. Example like leave management. User apply, next send to manager will approve (1st approval). After manager approved, next the will going to supervisor for 2nd approval within their division. For example user at IT division will send to IT manager then next to IT supervisor.
You could do this by having 4 models, user, manager, approval, and project Have a user has many relationship for projects Manager hasMany users Approval hasmany managers. Set an ending manager field on the model When user submits a project, manager is notified, clicks a button and process repeats until it reaches the "ending manager" user... and if it is, then mark as approved or completed. You might want to add a model for attachments or something i guess
@@ramleeatan8636 just take it step by step. The first and main bit i think to have this work is understand eloquent relationships. Take these relationships that i have outlined here and try snd make them work. Once you have them down.. the interactions are the bit that isndown to your preference. Personally i would just have it inform the users->managers email address that they have a new item assigned to.them and display a link to it.. After that a check at that stage when they "approve it" that checks if they are.the final "point of contact" and if so... mark as complete. Once you have.that down, give the abilitynto mark as in progress etc and send it back as needing work and you have a pretty neat sysyem
You should not DELETE invoices, ever, according to accountants. You need to change the status, or something. Or maybe use soft-delete in this case, and then calculate next ID using withTrashed()
@@sweetsong7954 I think I answered your question already. But if you want to use hard-delete, then probably you need to store max_number elsewhere, for example in series DB table, and calculate from there.
Completely wrong! Where are you locking the table to prevent another user from generating the same number at the same time? This solution will cause big problems if there is more than one user.
Quick tip: Don't use uuid as primary_id? 🚨 some developers delete "id int primary auto-increment" and set id char(36) for uuid here are some issues you can face. what about your thoughts if we drop "id int primary_key auto-increment"? according to my experiment never drop "int id primary auto-increment, instead make 2nd column called uuid or external_id of uuid dattype char(36). I know its not good because of db storage but think about if any primary_id deleted suppose 5, then new record id will be 6 and we can't force new id to 5 but in case of uuid you can use the uuid of deleted row because uuid is not set to primary. Even if we set uuid column as primary with auto_increment off then still we can face same issue. same issue with unique you can use old uuid 2nd time if previous record deleted but in case of "id int primary_key auto-increment" you can't and we need to go with it.
Exactly what i was looking for. The way you adding the number using Creating event on the model and they way you are finding the next incremental number with max. (thumbsup)
Using max + 1 is dangerous: if you delete the latest entry and after that create a new entry, it will get the same id as the entry before. Better approach: use the ids only internal and not visible to the frontend. Instead show UUIDs on the frontend. UUIDs are also safer because you cannot guess the ids of an item. But use the integer ids internal because joining between integers is way faster than between strings (that's what UUIDs are in MySQL for example).
Ids only internal means? and are those internal IDs auto-increment or doing them manually increment?
@@ehtashamshami6969 internal means that you only use them to build relationships between entities. But you never show them to the outer world. From the outside you use the uuids (or what I use personally: nanoids with ZBase32) to identify an entity. An yes, the "internal ids" use autoincroment to prevent collisions.
Good video! A third and intermediary option would be to have a mutator getFullNumber that executes that logic without requiring the view to do it or a field in the database. This way you can call the full_number as an attribute without the hassle of storing duplicated data.
But you always need to store all transaction data just as the same as when they were created. Imagine when the company decides to change the prefix at some time later, all invoice numbers in the past will also change, which is obviously not a good thing.
I needed to implement this in one of my current prokects. Thanks
Hi, nice quick and concise.
Only downside i can see to creating them on the fly and not storing ffull invoice number, is that if you update your prefix, customers previous invoices would change. Which for accounting is not ideal.
Great video thank you! However, at 1:25, I would recommend to put the logic in a transaction to avoid raise conditions.
That's why I haven't used event creating for such cases. I created a service and called the ServiceName::generate() in the controller store method.
thanks for the video!
you will get a a PDO error in case of creating few invoices at the same time (if you have unique key for number+series_id) or you will get few invoices with the same full number. Reason a DB query to fetch latest invoice number with current series_id takes some time and if you have few requests to create an invoice at the same time, most likely this DB query will return the same result. For big DB tables with few indices it's a pretty common problem for approaches like this.
In order to avoid this problem, you can use locks or set full_number in a queue
How do I use locks?
Your videos are great and helping a lot. Thank you so much. One request, kindly make a video on Complex relations in laravel Eloquent
Thanks for kind words.
1. I already have a lot of videos about Eloquent, here are search results: ruclips.net/channel/UCTuplgOBi6tJIlesIboymGAsearch?query=eloquent
2. The biggest set of information on that topic is in my course "Eloquent: Expert Level" bit.ly/eloquent-course
An important note to mention is this context is that , you need to keep tracking of the serial number of invoices , so the delete invoices could be noted , lets say that you will use soft delete option in laravel , then you has to add withTrashed() scop to Invoice::where('series_id', $model->series_id)->max('number) +1
so you can keep the serial correctly and there are no serial overlap could happened in this case.
Incredible video, please how could it be done so that it returns to number 1 at the beginning of the year or at the beginning of the month ?
such a nice person you are, Your tips very helpful. After watched this video I implement it in my project. I am very happy after seeing the results.
Thank you very much! I learn a lot through your videos
You saved my day
you can use int(5) unsigned zerofill in db. You insert value like 1, in db it was 0001
Nice tips! But, what if I want to reset it for every once in a year?
@@thomaspotterdotexe Hello :) did you managed to solve how to reset it every year? I’m kinda curious how I can do it too as a complete beginner.
I love your tutorials sir. I am a beginner learning laravel, I would like to request if you have a tutorial making a full working application step by step. It will help me a lot in advancing my knowledge. Thank you.
I've done a lot of live-coding in the past, like this: ruclips.net/video/Oq_b1g_JpCM/видео.html
But it takes a very long time, to be honest. So maybe I will do that only in the form of a premium course, just to pay off my time spent. Would you buy something like in that playlist for, say, $19? (which is a typical price for any of my courses here - laraveldaily.teachable.com)
@@PovilasKorop yes Sir am ready to buy that in order to learn,because I see your tutorials are far much worthy than that.
@@PovilasKorop yes :D
is this safe concurrently? wouldn't that cause a conflict when several models are created at the same time?
Your videos are always amazing. Thanks
Thank you very much for your video tutorials.
my creating event is never fired
static::creating(function ($model) {
error_log('creating');
$model->nice_number = str_pad($model->unit_number, 4, 0, STR_PAD_LEFT);
});
Any ideas?
sir wich datatables did you use?
Thanks man!
Is there a possibility of competition between users and the max function returns the same number when generating the invoice? If so, what can we do to avoid it?
Yes, there is a (very small) possibility of that happening. If you want to be very careful, you could use a database transaction to have it all in one go, or perform one SQL query like "insert into invoices (select max from series) ..."
I faced this issue, this may happen. Duplicate serial number.
Will this method works when many people are hit it at the same time?
Thanks for these man! Awesome tutorials.
nice and clean tutorial. thank you.
this is very useful, thaks
is it good if I use concat()?
easy way to use accessors and mutators laravel.com/docs/7.x/eloquent-mutators#accessors-and-mutators
example: Put this in the model you want to change the id from
public function getIdAttribute($value)
{
return str_pad($value, 5, '0', STR_PAD_LEFT);
}
Trying to get property 'prefix' of non-object: $model->serie->prefix; how to solve it?
awesome, this is easy to implement
Won't this cause a race condition when there are multiple invoice generations at the same time?
To put the Invoice number generation in a queue would help.
Thank you sir
Can you tell me which package is used for that table?
That was our own quickadminpanel.com generator
@@PovilasKorop oh. Okay. I thought you were using some open source package.
But why not use Accessors & Mutators to get invoice id instead of store separate column into db !?
Maybe it will be more elegant to format the number in a mutator in the model
Thanks for the ideas. But I think invoice should calculated after created.
That's a personal preference, I guess.
@@PovilasKorop yes depends on application if multi user create on the same time it causes duplicate invoice number.
Great tutorial sir 👍. If you don't mind, would you sharing about how to handle multiple approval (user to manager to supervisor) with division (IT/HR/Finance). Tq so much
Can you please give more details, how it should work exactly, what is "multiple approval" or give any link to the description of other existing system.
@@PovilasKorop sorry if you got confused. Example like leave management. User apply, next send to manager will approve (1st approval). After manager approved, next the will going to supervisor for 2nd approval within their division. For example user at IT division will send to IT manager then next to IT supervisor.
You could do this by having 4 models, user, manager, approval, and project
Have a user has many relationship for projects
Manager hasMany users
Approval hasmany managers. Set an ending manager field on the model
When user submits a project, manager is notified, clicks a button and process repeats until it reaches the "ending manager" user... and if it is, then mark as approved or completed.
You might want to add a model for attachments or something i guess
@@jamesmcconnon2 thanks you so much.. That what i mean.. BTW, I'm a beginner for laravel. 😂😂. The coding might be the nightmare for me😅😅
@@ramleeatan8636 just take it step by step. The first and main bit i think to have this work is understand eloquent relationships. Take these relationships that i have outlined here and try snd make them work.
Once you have them down.. the interactions are the bit that isndown to your preference. Personally i would just have it inform the users->managers email address that they have a new item assigned to.them and display a link to it..
After that a check at that stage when they "approve it" that checks if they are.the final "point of contact" and if so... mark as complete.
Once you have.that down, give the abilitynto mark as in progress etc and send it back as needing work and you have a pretty neat sysyem
Is it possible to do the same through accessors and mutators? Will this be the right way too?
Of course you can. Carry the same logic he uses over to your accessors/mutators
thank you bro
But it does not work when updating😇
Hello , i have 2 records on invoice Ex.invo_no1 and invo_no2 and then i delete invo_no2 next i create new record but only show invo_no2 how to do?
You should not DELETE invoices, ever, according to accountants. You need to change the status, or something. Or maybe use soft-delete in this case, and then calculate next ID using withTrashed()
@@PovilasKorop in this case what i should to do if they want to delete
@@sweetsong7954 I think I answered your question already. But if you want to use hard-delete, then probably you need to store max_number elsewhere, for example in series DB table, and calculate from there.
@@PovilasKorop you could show for me? how to store max_number
@@sweetsong7954
php artisan make:migration add_max_number_to_series_table
$table->integer('max_number')->default(0);
Invoice.php model -> boot() -> creating()
$series = Series::find($model->series_id);
$model->number = ->max_number + 1;
$series->increment('max_number');
Something like that. Didn't test, try it out.
Thanks
Completely wrong!
Where are you locking the table to prevent another user from generating the same number at the same time? This solution will cause big problems if there is more than one user.
I'm afraid Robber is right. There is the possibility of the same invoice numbers. To put the Invoice generation in a queue would help.
would this be solved if we guard it within transaction?
niceeeee bro
Great
Quick tip: Don't use uuid as primary_id? 🚨
some developers delete "id int primary auto-increment" and set id char(36) for uuid here are some issues you can face.
what about your thoughts if we drop "id int primary_key auto-increment"? according to my experiment never drop "int id primary auto-increment, instead make 2nd column called uuid or external_id of uuid dattype char(36). I know its not good because of db storage but think about if any primary_id deleted suppose 5, then new record id will be 6 and we can't force new id to 5 but in case of uuid you can use the uuid of deleted row because uuid is not set to primary. Even if we set uuid column as primary with auto_increment off then still we can face same issue. same issue with unique you can use old uuid 2nd time if previous record deleted but in case of "id int primary_key auto-increment" you can't and we need to go with it.