Custom auto incrementing fields for string giving duplicate entries





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















I am currently working on an application that requires that every student registered in the system have a unique registration number upon registration which is auto incrementing for every registration. The registration number should be of the format "01/19" for the first student registered in 2019, "890/19" for 890th student etc.



The data for registration is uploaded from kobo data collection tool therefore it comes to my endpoint within very close time intervals as close to 200 submission can be done once.



I realized that out of 1000 records there are close to 27 duplicate registration numbers. This is how I have implemented the registration number generation logic



def registration_changeset(student, attrs) do
student |> changeset(attrs) |> Accounts.add_registration_number()
end


Then the Accounts context has the following code for adding registration number



def add_registration_number(changeset) do
struct = changeset.data.__struct__
registration_number =
case struct |> last() |> Repo.one() do
nil -> _create_new_registration_number()
resource -> _increment_registration(resource.registration_number)
end

put_change(changeset, :registration_number, registration_number)
end


I am betting on the last created student to be having the latest registration number in the above case



Is there a better way of implementing this?










share|improve this question





























    0















    I am currently working on an application that requires that every student registered in the system have a unique registration number upon registration which is auto incrementing for every registration. The registration number should be of the format "01/19" for the first student registered in 2019, "890/19" for 890th student etc.



    The data for registration is uploaded from kobo data collection tool therefore it comes to my endpoint within very close time intervals as close to 200 submission can be done once.



    I realized that out of 1000 records there are close to 27 duplicate registration numbers. This is how I have implemented the registration number generation logic



    def registration_changeset(student, attrs) do
    student |> changeset(attrs) |> Accounts.add_registration_number()
    end


    Then the Accounts context has the following code for adding registration number



    def add_registration_number(changeset) do
    struct = changeset.data.__struct__
    registration_number =
    case struct |> last() |> Repo.one() do
    nil -> _create_new_registration_number()
    resource -> _increment_registration(resource.registration_number)
    end

    put_change(changeset, :registration_number, registration_number)
    end


    I am betting on the last created student to be having the latest registration number in the above case



    Is there a better way of implementing this?










    share|improve this question

























      0












      0








      0








      I am currently working on an application that requires that every student registered in the system have a unique registration number upon registration which is auto incrementing for every registration. The registration number should be of the format "01/19" for the first student registered in 2019, "890/19" for 890th student etc.



      The data for registration is uploaded from kobo data collection tool therefore it comes to my endpoint within very close time intervals as close to 200 submission can be done once.



      I realized that out of 1000 records there are close to 27 duplicate registration numbers. This is how I have implemented the registration number generation logic



      def registration_changeset(student, attrs) do
      student |> changeset(attrs) |> Accounts.add_registration_number()
      end


      Then the Accounts context has the following code for adding registration number



      def add_registration_number(changeset) do
      struct = changeset.data.__struct__
      registration_number =
      case struct |> last() |> Repo.one() do
      nil -> _create_new_registration_number()
      resource -> _increment_registration(resource.registration_number)
      end

      put_change(changeset, :registration_number, registration_number)
      end


      I am betting on the last created student to be having the latest registration number in the above case



      Is there a better way of implementing this?










      share|improve this question














      I am currently working on an application that requires that every student registered in the system have a unique registration number upon registration which is auto incrementing for every registration. The registration number should be of the format "01/19" for the first student registered in 2019, "890/19" for 890th student etc.



      The data for registration is uploaded from kobo data collection tool therefore it comes to my endpoint within very close time intervals as close to 200 submission can be done once.



      I realized that out of 1000 records there are close to 27 duplicate registration numbers. This is how I have implemented the registration number generation logic



      def registration_changeset(student, attrs) do
      student |> changeset(attrs) |> Accounts.add_registration_number()
      end


      Then the Accounts context has the following code for adding registration number



      def add_registration_number(changeset) do
      struct = changeset.data.__struct__
      registration_number =
      case struct |> last() |> Repo.one() do
      nil -> _create_new_registration_number()
      resource -> _increment_registration(resource.registration_number)
      end

      put_change(changeset, :registration_number, registration_number)
      end


      I am betting on the last created student to be having the latest registration number in the above case



      Is there a better way of implementing this?







      elixir phoenix-framework ecto






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 3 at 16:06









      Sigu MagwaSigu Magwa

      326314




      326314
























          2 Answers
          2






          active

          oldest

          votes


















          1














          You need a bit of synchronized code here :)



          Create a dedicated process that will serve the single purpose: producing numbers. GenServer.handle_call/3 already does whatever you need, the process mailbox is the perfect queue and OTP would do everything for you.





          defmodule MyApp.RegNumHelper do
          @moduledoc false

          use GenServer

          def start_link(opts),
          do: GenServer.start_link(__MODULE__, opts, name: name)

          def add_registration_number(changeset),
          do: GenServer.call(__MODULE__, {:reg_num, changeset})


          @impl true
          def init(opts), do: {:ok, opts}

          @impl true
          def handle_call({:reg_num, changeset}, _from, state) do
          # your logic assigning changeset
          {:reply, changeset, state}
          end
          end


          This approach has another advantage: since the process is already stateful you do not actually need to query the DB every time. Just query it on process start and save the current number into state.






          share|improve this answer































            0














            The simplest solution is that you could just let the auto-incremented ID be the first part of the registration number and store the two-digit year as a field by itself. Then in the model you would simply have a method 'get_registration_number' that composes the two. This resolves the duplicate problem.



            The downside is that you would then have, say 890/19 as the last student in 2019, and then 891/20 as the first student in 2020 instead of 01/20. But your example doesn't quite appear to handle that case either, and it is implied, but not clear, that this is a requirement.



            Which if it is, you could instead of letting the ID be the first part, create a column that auto-increments as before (id_num, say) and then when the year changes reset the next value to 1 on that column. If you wanted to be paranoid you could say the 'id_num' column and the 'two_digit_year' column together form a unique key.



            TL;DR: The easiest way to handle this is to let the database handle it.






            share|improve this answer


























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54025893%2fcustom-auto-incrementing-fields-for-string-giving-duplicate-entries%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              1














              You need a bit of synchronized code here :)



              Create a dedicated process that will serve the single purpose: producing numbers. GenServer.handle_call/3 already does whatever you need, the process mailbox is the perfect queue and OTP would do everything for you.





              defmodule MyApp.RegNumHelper do
              @moduledoc false

              use GenServer

              def start_link(opts),
              do: GenServer.start_link(__MODULE__, opts, name: name)

              def add_registration_number(changeset),
              do: GenServer.call(__MODULE__, {:reg_num, changeset})


              @impl true
              def init(opts), do: {:ok, opts}

              @impl true
              def handle_call({:reg_num, changeset}, _from, state) do
              # your logic assigning changeset
              {:reply, changeset, state}
              end
              end


              This approach has another advantage: since the process is already stateful you do not actually need to query the DB every time. Just query it on process start and save the current number into state.






              share|improve this answer




























                1














                You need a bit of synchronized code here :)



                Create a dedicated process that will serve the single purpose: producing numbers. GenServer.handle_call/3 already does whatever you need, the process mailbox is the perfect queue and OTP would do everything for you.





                defmodule MyApp.RegNumHelper do
                @moduledoc false

                use GenServer

                def start_link(opts),
                do: GenServer.start_link(__MODULE__, opts, name: name)

                def add_registration_number(changeset),
                do: GenServer.call(__MODULE__, {:reg_num, changeset})


                @impl true
                def init(opts), do: {:ok, opts}

                @impl true
                def handle_call({:reg_num, changeset}, _from, state) do
                # your logic assigning changeset
                {:reply, changeset, state}
                end
                end


                This approach has another advantage: since the process is already stateful you do not actually need to query the DB every time. Just query it on process start and save the current number into state.






                share|improve this answer


























                  1












                  1








                  1







                  You need a bit of synchronized code here :)



                  Create a dedicated process that will serve the single purpose: producing numbers. GenServer.handle_call/3 already does whatever you need, the process mailbox is the perfect queue and OTP would do everything for you.





                  defmodule MyApp.RegNumHelper do
                  @moduledoc false

                  use GenServer

                  def start_link(opts),
                  do: GenServer.start_link(__MODULE__, opts, name: name)

                  def add_registration_number(changeset),
                  do: GenServer.call(__MODULE__, {:reg_num, changeset})


                  @impl true
                  def init(opts), do: {:ok, opts}

                  @impl true
                  def handle_call({:reg_num, changeset}, _from, state) do
                  # your logic assigning changeset
                  {:reply, changeset, state}
                  end
                  end


                  This approach has another advantage: since the process is already stateful you do not actually need to query the DB every time. Just query it on process start and save the current number into state.






                  share|improve this answer













                  You need a bit of synchronized code here :)



                  Create a dedicated process that will serve the single purpose: producing numbers. GenServer.handle_call/3 already does whatever you need, the process mailbox is the perfect queue and OTP would do everything for you.





                  defmodule MyApp.RegNumHelper do
                  @moduledoc false

                  use GenServer

                  def start_link(opts),
                  do: GenServer.start_link(__MODULE__, opts, name: name)

                  def add_registration_number(changeset),
                  do: GenServer.call(__MODULE__, {:reg_num, changeset})


                  @impl true
                  def init(opts), do: {:ok, opts}

                  @impl true
                  def handle_call({:reg_num, changeset}, _from, state) do
                  # your logic assigning changeset
                  {:reply, changeset, state}
                  end
                  end


                  This approach has another advantage: since the process is already stateful you do not actually need to query the DB every time. Just query it on process start and save the current number into state.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jan 4 at 6:31









                  Aleksei MatiushkinAleksei Matiushkin

                  84.8k95896




                  84.8k95896

























                      0














                      The simplest solution is that you could just let the auto-incremented ID be the first part of the registration number and store the two-digit year as a field by itself. Then in the model you would simply have a method 'get_registration_number' that composes the two. This resolves the duplicate problem.



                      The downside is that you would then have, say 890/19 as the last student in 2019, and then 891/20 as the first student in 2020 instead of 01/20. But your example doesn't quite appear to handle that case either, and it is implied, but not clear, that this is a requirement.



                      Which if it is, you could instead of letting the ID be the first part, create a column that auto-increments as before (id_num, say) and then when the year changes reset the next value to 1 on that column. If you wanted to be paranoid you could say the 'id_num' column and the 'two_digit_year' column together form a unique key.



                      TL;DR: The easiest way to handle this is to let the database handle it.






                      share|improve this answer






























                        0














                        The simplest solution is that you could just let the auto-incremented ID be the first part of the registration number and store the two-digit year as a field by itself. Then in the model you would simply have a method 'get_registration_number' that composes the two. This resolves the duplicate problem.



                        The downside is that you would then have, say 890/19 as the last student in 2019, and then 891/20 as the first student in 2020 instead of 01/20. But your example doesn't quite appear to handle that case either, and it is implied, but not clear, that this is a requirement.



                        Which if it is, you could instead of letting the ID be the first part, create a column that auto-increments as before (id_num, say) and then when the year changes reset the next value to 1 on that column. If you wanted to be paranoid you could say the 'id_num' column and the 'two_digit_year' column together form a unique key.



                        TL;DR: The easiest way to handle this is to let the database handle it.






                        share|improve this answer




























                          0












                          0








                          0







                          The simplest solution is that you could just let the auto-incremented ID be the first part of the registration number and store the two-digit year as a field by itself. Then in the model you would simply have a method 'get_registration_number' that composes the two. This resolves the duplicate problem.



                          The downside is that you would then have, say 890/19 as the last student in 2019, and then 891/20 as the first student in 2020 instead of 01/20. But your example doesn't quite appear to handle that case either, and it is implied, but not clear, that this is a requirement.



                          Which if it is, you could instead of letting the ID be the first part, create a column that auto-increments as before (id_num, say) and then when the year changes reset the next value to 1 on that column. If you wanted to be paranoid you could say the 'id_num' column and the 'two_digit_year' column together form a unique key.



                          TL;DR: The easiest way to handle this is to let the database handle it.






                          share|improve this answer















                          The simplest solution is that you could just let the auto-incremented ID be the first part of the registration number and store the two-digit year as a field by itself. Then in the model you would simply have a method 'get_registration_number' that composes the two. This resolves the duplicate problem.



                          The downside is that you would then have, say 890/19 as the last student in 2019, and then 891/20 as the first student in 2020 instead of 01/20. But your example doesn't quite appear to handle that case either, and it is implied, but not clear, that this is a requirement.



                          Which if it is, you could instead of letting the ID be the first part, create a column that auto-increments as before (id_num, say) and then when the year changes reset the next value to 1 on that column. If you wanted to be paranoid you could say the 'id_num' column and the 'two_digit_year' column together form a unique key.



                          TL;DR: The easiest way to handle this is to let the database handle it.







                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Jan 3 at 22:46

























                          answered Jan 3 at 22:41









                          JustAnotherSoulJustAnotherSoul

                          263313




                          263313






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54025893%2fcustom-auto-incrementing-fields-for-string-giving-duplicate-entries%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              MongoDB - Not Authorized To Execute Command

                              in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith

                              Npm cannot find a required file even through it is in the searched directory