Avatar billede groyk Novice
13. december 2012 - 14:42 Der er 17 kommentarer og
1 løsning

Faktura nummer serie

Hej Eksperter

Arbejder på sidste etape af fakturagenerering i et "CMS/ERP" system.

Men hvad er "best practice" for trækning af numre.

Jeg forventer egentlig bare at benytte auto_increment på kolonnen "invoice_no" og så sætte counteren til det tal der skal fortsættes fra.

Naturligvis vil alle skrivninger blive kørt som transaktioner, så der ikke opstår fejl.
Avatar billede arne_v Ekspert
13. december 2012 - 21:24 #1
Jeg tror ikke at det er en god loesning.

I forbindelse med rollback vil der kunne opstaa huller i numrene.

Og saa vidt jeg ved er huller i faktura numre ikke godt i henhold til revisorer.
Avatar billede groyk Novice
14. december 2012 - 09:47 #2
Hej Arne

Er der mulighed for rollback i MySQL?? Vidste jeg ikke.

Måske det er bedre at søge efter højeste nr. i tabellen og lægge en til hver gang der genereres en faktura. På den måde burde der ikke kunne opstå et hul i faktura rækkefølgen.

Det burde vel ikke give problemer med dubletter såfremt det køres i en samlet transaktion??
Avatar billede arne_v Ekspert
14. december 2012 - 14:29 #3
InnoDB tabeller understoetter transaktioner og dermed commit/rollback.
Avatar billede arne_v Ekspert
14. december 2012 - 14:30 #4
SELECT MAX+1 er som udgangspunkt ikke sikker for flere samtidige bruge. Du vil skulle op i transaction isolation level serializable.
Avatar billede groyk Novice
14. december 2012 - 19:27 #5
Hm. Lyder som om det teknisk ikke er muligt med adgang direkte fra brugerniveau. Hvad synes du om hvis man sætter et "flag" klar til fakturering, og så kører et cronjob eks. Hvert minut der trækker nummeret og generere fakturaen.

Denne løsning er dog ikke helt så flexibel, da der ikke genereres fakturaer "instant"

Dog noget kompliceret forhold til at  lave noget af
Trans start
Træk højeste nr.
Indsæt faktura nr.
Trans commit

Faktura nummeret skal indsættes i en ordre tabel i kolonnen "invoice_no" kolonnen er UNIQ og kan indeholde NULL sidstnævnte bruges hvis en ordre ikke ender ud i en faktura.

Når tabellen ser ud som denne, vil "dobbelt trækninger" vel ende ud i en fejl og ikke 2 fakturaer med samme nr.?


Ps. Er rollback = ikke at commite en transaktion?

Pps. Er der nogle der har erfaringer fra andre finans systemer.
Avatar billede groyk Novice
14. december 2012 - 20:57 #6
Søgte lige efter only one instance og faldt over følgende PHP Script.

Tror det bliver den vej jeg går.

1. Sikrer mig at der kun kan køres et script af gangen. (Se nedenstående PHP script)
2. Kontrollere at ordren må faktureres. (er den leveret eller er den faktureret tidligere)
2. Trækker højeste nr. i tabellen og lægger 1 til.
3. Indsætter faktura nr. samt andre nødvendige data.
4. Generere PDF faktura og gemmer i systemmappe, hvor kun systemet har adgang til
5. Sender faktura (email, printer, m.v.)
6. skriver til logfil. Faktnr, Ordrenr, pdffil, emailed, printet ect.

Er der noget jeg ikke har tænkt på??

<?php
  $run = basename($_SERVER['PHP_SELF'], '.php') . '.run';
  //  Kan evt. erstattes med et unikt ID hvis det eksempelvis kun        //er en funktion der kun må køre en gang

  if (!file_exists($run) {
    touch($run);
    register_shutdown_function('shutdown', $run);
    $microtime = microtime();
    file_put_contents($run, $microtime);
  }
  else {
    echo "Already running!";
    exit;
  }

  // ... (some code)
  sleep($waitForFirstStartup);// dynamic calculated value

  while (file_exists($run) && file_get_contents($run) == $microtime) {
    // ... (rest of code)
    sleep($waitBetweenStuffToDo);// dynamic calculated value
  }

  function shutdown($run) {
    unlink($run);
  }
?>
Avatar billede arne_v Ekspert
15. december 2012 - 01:28 #7
Trans start
Træk højeste nr.
Indsæt faktura nr.
Trans commit

vil igen kraeve transaction isolation level serializable
Avatar billede arne_v Ekspert
15. december 2012 - 01:30 #8
RePS: Nej rollback er at rulle tilbage til start (skipper alle rettelserne) mens commit gemmer alle rettelsene.
Avatar billede arne_v Ekspert
15. december 2012 - 01:31 #9
Jeg kan ikke se pointen i den PHP kode.

Den vil vaere langsommere end transaction isolation level serializable og den er mindre robust.
Avatar billede groyk Novice
15. december 2012 - 22:16 #10
OK, Men hvordan sætter jeg "transaction isolation level serializable" op i min php fil?
Avatar billede arne_v Ekspert
15. december 2012 - 22:26 #11
Avatar billede groyk Novice
15. december 2012 - 22:34 #13
Fandt måske noget efter noget søgning

SET TRANSACTIOn ISOLATION LEVEL SERIALIZABLE;
BEGIN;

// Min SQL kode

COMMIT;

Kontroller om der er sket fejl?

Er jeg på rette spor?
Avatar billede arne_v Ekspert
15. december 2012 - 22:35 #14
Ja
Avatar billede groyk Novice
15. december 2012 - 22:50 #15
$this->db->query('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;');
        $this->db->trans_start();
       
        $query = $this->db->query('SELECT @@tx_isolation;');
        $test = $query->result();
       
        print_r($test);
   
        $this->db->trans_complete();
           
        if ($this->db->trans_status() === FALSE)
        {
                // generate an error... or use the log_message() function to log your error
        }

Det var jo egentligt meget simpelt
Avatar billede groyk Novice
15. december 2012 - 22:51 #16
Takker for hjælpen, venligst smid et svar. Burde have givet mere end 30 point :-)
Avatar billede arne_v Ekspert
15. december 2012 - 23:04 #17
svar
Avatar billede arne_v Ekspert
15. december 2012 - 23:25 #18
Du har engang laest http://www.eksperten.dk/guide/996, men maaske var den vaerd at genlaese. Den er ikke paa et ret hoejt niveau, men den giver nogle termer som man kan google videre paa.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester