AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Vorgehensweise für Rechnungsnummernvergabe im Multi-User Betrieb

Vorgehensweise für Rechnungsnummernvergabe im Multi-User Betrieb

Ein Thema von RWarnecke · begonnen am 27. Nov 2011 · letzter Beitrag vom 28. Nov 2011
Antwort Antwort
Seite 2 von 2     12
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.269 Beiträge
 
Delphi 10.4 Sydney
 
#11

AW: Vorgehensweise für Rechnungsnummernvergabe im Multi-User Betrieb

  Alt 28. Nov 2011, 08:10
Hallo,

die Sache mit dem Generator hat aber mit der Rechnungsnummer nichts zu tun (?).
Es gibt 2 Felder, RechnungsID (PrimKey,über Generator) und RechnungsNr(über eigene Logik, z.B. Sperrtabelle).


Heiko
Heiko
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#12

AW: Vorgehensweise für Rechnungsnummernvergabe im Multi-User Betrieb

  Alt 28. Nov 2011, 08:40
Na, die Idee stand im Raum, das man für die Rechnungs-Nr auch einen Generator verwendet.
Ich halte aber die Tabelle mit allen Rechnungsnummern (der nächsten 100 Jahre ) für den einzig richtigen Weg, um Lücken zu vermeiden.

Es ist ja schwer, dem Finanzamt zu vermitteln, weshalb Rechnung Nr.: 12345 nicht eingereicht wurde. Die interessiert dann nicht, wenn man dann die DB-Logdatei vorzeigt, der belegt, das eine Transaktion aufgrund was-weiss-ich fehlschlug.

Allerdings muss man bei der Lösung sicherstellen, das zu Ultimo (z.B. Monatsende) keine Lücken vorhanden sind.
  Mit Zitat antworten Zitat
Benutzerbild von MGC
MGC

Registriert seit: 15. Mai 2008
Ort: Helsa
106 Beiträge
 
Turbo Delphi für Win32
 
#13

AW: Vorgehensweise für Rechnungsnummernvergabe im Multi-User Betrieb

  Alt 28. Nov 2011, 09:14
Das Finanzamt sollte mittlerweile aber Erfahrung im Einsatz von DBMS haben udn wissen, dass es immer wieder mal zu Fehlern kommen kann.

Aufgrund der beschriebenen Architektur würde ich persönlich auch noch immer dabei bleiben die Re-Nr. erst zu vergeben, wenn die Rechnung tatsächlich gespeichert wird.
Bei der Rechnungsspeicherung darf es dann, wie bereits erwähnt, kein Rollback geben.

Man kann natürlich auch darauf vertrauen, dass es, aufgrund weniger Rechnungsstellungen pro Tag, hoffentlich niemals zu einem zeitgleichen Speichervorgang in der DB kommt, aber das wäre mir zu wage.
Marc
Programmieren ist wie Chemie:
1. Wenn man alles einfach nur zusammenschmeisst kommt es zu unerwarteten Reaktionen.
2. Wenn es plötzlich anfängt zu qualmen, muss man eben noch mal von vorn anfangen.
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#14

AW: Vorgehensweise für Rechnungsnummernvergabe im Multi-User Betrieb

  Alt 28. Nov 2011, 10:10
OT:
Ist das wirklich so, dass das Finanzamt auf sowas besteht?
Dann vielleicht zum Monatsende oder Quartalsabschluss eine extra Liste mit fortlaufenden Nummern und Verweise auf die "interne" Rechnungsnummer produzieren und abheften.
Gruß, Jo
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#15

AW: Vorgehensweise für Rechnungsnummernvergabe im Multi-User Betrieb

  Alt 28. Nov 2011, 10:13
Mit MySQL würde das so aussehen:
Code:
CREATE TABLE `beltab` (
`BelID`  bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT ,
`BelTyp`  varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`BelNr`  int(11) NOT NULL DEFAULT 0 ,
`BelInfo`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`BelID`),
UNIQUE INDEX `UNQ_Typ_Nr` (`BelTyp`, `BelNr`) USING BTREE
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
AUTO_INCREMENT=1044
ROW_FORMAT=COMPACT;

CREATE DEFINER=`root`@`%` TRIGGER `beltab_before_insert` BEFORE INSERT ON `NewTable`
FOR EACH ROW SET NEW.BelNr = GetNewScopeLfd( NEW.BelTyp );

CREATE TABLE `tbl_lfd` (
`Scope`  varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`LastLfd`  int(11) NOT NULL ,
`Step`  int(11) NOT NULL DEFAULT 1 ,
PRIMARY KEY (`Scope`)
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
ROW_FORMAT=COMPACT;

CREATE DEFINER = `root`@`%` FUNCTION `GetNewScopeLfd`(Scope varchar(50))
 RETURNS int(11)
BEGIN
   DECLARE NewLfd int;

   UPDATE tbl_lfd
      SET LastLfd = LastLfd + Step
      WHERE tbl_lfd.Scope = Scope;

   SELECT LastLfd
      INTO NewLfd
      FROM tbl_lfd
      WHERE tbl_lfd.Scope = Scope;

   RETURN NewLfd;
END;
Zum Testen habe ich folgendes (mit 10+ Programm-Instanzen) ausführen lassen:
Delphi-Quellcode:
unit View.Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs, DB, DBAccess, Uni, UniProvider,
  MySQLUniProvider, StdCtrls, ExtCtrls;

type
  TForm1 = class( TForm )
    MySQLUniProvider1 : TMySQLUniProvider;
    UniConnection1 : TUniConnection;
    Timer1 : TTimer;
    CheckBox1 : TCheckBox;
    procedure CheckBox1Click( Sender : TObject );
    procedure Timer1Timer( Sender : TObject );
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1 : TForm1;

implementation

{$R *.dfm}

procedure TForm1.CheckBox1Click( Sender : TObject );
begin
  Timer1.Enabled := CheckBox1.Checked;
end;

procedure TForm1.Timer1Timer( Sender : TObject );
begin
  Timer1.Enabled := False;

  if not UniConnection1.Connected
  then
    UniConnection1.Open;

  UniConnection1.StartTransaction;
  try

    UniConnection1.ExecSQL( 'INSERT INTO beltab (BelTyp, BelInfo) VALUES(:BelTyp,:BelInfo);',
      ['RECHNUNG', 'Nur so'] );

    Sleep( 250 );

    if Random( 2 ) = 1
    then
      UniConnection1.Commit
    else
      UniConnection1.Rollback;

  except
    UniConnection1.Rollback;
  end;

  Timer1.Enabled := CheckBox1.Checked;
end;

end.
Es treten weder Lücken auf, noch kommt es zu Ausnahmen, weil eine Beleg-Nummer doppelt vergeben wurde.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von ChrisE
ChrisE

Registriert seit: 15. Feb 2006
Ort: Hechingen
504 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#16

AW: Vorgehensweise für Rechnungsnummernvergabe im Multi-User Betrieb

  Alt 28. Nov 2011, 10:16
OT:
Ist das wirklich so, dass das Finanzamt auf sowas besteht?
OT:
Soweit ich weiß, ist nur eine eindeutige aber keine fortlaufende Nummer wichtig. Da gab es ein paar Entscheidungen, da man gegenüber einem Kunden den Rückschluss auf die Anzahl der Rechnungen einer Firma verhindern wollte.
Christian E.
Es gibt 10 Arten von Menschen, die die Binär lesen können und die die es nicht können

Delphi programming rules
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#17

AW: Vorgehensweise für Rechnungsnummernvergabe im Multi-User Betrieb

  Alt 28. Nov 2011, 10:19
In der Dokumentation von MySQL steht dazu folgendes:
Zitat von MySQL Dokumentation 5.1:
Betrachten wir ein anderes Beispiel: Wir haben in der Tabelle child_codes ein Zählerfeld eines Integer-Typs, das wir dazu benutzen, jedem Kind, das der child-Tabelle hinzugefügt wird, eine eindeutige Kennnummer zu geben. Da wäre es natürlich keine gute Idee, den Wert des Zählers mit einer konsistenten Leseoperation oder im Shared-Modus zu lesen, da zwei Datenbanknutzer dann vielleicht denselben Zählerwert sehen und einen Fehler wegen Schlüsselduplikaten auslösen, sofern sie versuchen, Kindeinträge mit derselben Nummer in die Tabelle einzufügen.

Hier ist LOCK IN SHARE MODE keine gute Lösung. Denn wenn zwei Benutzer gleichzeitig den Zähler lesen, könnte mindestens einer von ihnen in einen Deadlock geraten, wenn er versucht, den Zähler zu aktualisieren.

Hier haben Sie zwei gute Möglichkeiten, das Lesen und Inkrementieren des Zählers zu implementieren: (1) Sie inkrementierten zuerst den Zähler um 1 und führen erst dann die Leseoperation durch, oder (2) Sie lesen den Zähler zuerst im Sperrmodus FOR UPDATE und inkrementieren ihn danach. Der zweite Ansatz kann folgendermaßen implementiert werden:
Code:
SELECT counter_field FROM child_codes FOR UPDATE;
UPDATE child_codes SET counter_field = counter_field + 1;
Ein SELECT … FOR UPDATE liest die neuesten verfügbaren Daten und errichtet eine exklusive Sperre auf jeder Zeile, die es liest. Somit setzt es dieselben Sperren, die auch ein Searched SQL UPDATE auf den Zeilen erwerben würde.

Die obige Beschreibung ist nur ein Beispiel dafür, wie SELECT … FOR UPDATE funktioniert. In MySQL können Sie einen eindeutigen Identifier grundsätzlich mit nur einem einzigen Tabellenzugriff generieren:
Code:
UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + 1);
SELECT LAST_INSERT_ID();
Die SELECT-Anweisung ruft nur die Identifier-Information ab (die für die aktuelle Verbindung spezifisch ist). Sie greift auf keine Tabellen zu.

Sperren von IN SHARE MODE- und FOR UPDATE-Leseoperationen werden freigegeben, wenn die Transaktion committet oder zurückgerollt wird.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
webcss

Registriert seit: 10. Feb 2006
255 Beiträge
 
Delphi XE2 Professional
 
#18

AW: Vorgehensweise für Rechnungsnummernvergabe im Multi-User Betrieb

  Alt 28. Nov 2011, 10:53
Ich denke auch, dass es lediglich um die Eindeutigkeit einer Rechnungsnummer zu einem Vorgang geht, d.h. keine doppelten Rechnungsnummern o.ä. Fortlaufend müssen diese aber nicht zwingend sein. Man schaue sich nur mal z.B. die Rechnungen von Amazon an, dort wird eine Folge von (alpha-)numerischen Zeichen in Groß- und Kleinschreibung sowie Ziffern verwendet. Diese sind wohl eindeutig, aber fortlaufend wohl kaum...
"Wer seinem Computer Mist erzählt, muss immer damit rechnen..." (unbekannt)
"Der Computer rechnet damit, dass der Mensch denkt..." (auch unbekannt)
mein blog
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
10.934 Beiträge
 
Delphi 12 Athens
 
#19

AW: Vorgehensweise für Rechnungsnummernvergabe im Multi-User Betrieb

  Alt 28. Nov 2011, 11:07
Ein Zitat der Oberfinanzdirektion Koblenz zu diesem Thema:

Zitat:
Nach den Erörterungen der obersten Finanzbehörden des Bundes und der Länder gilt Folgendes:

...

Angabe einer fortlaufenden Nummer in der Rechnung
Die in § 14 Abs. 4 S. 1 Nr. 4 UStG enthaltene Pflichtangabe einer fortlaufenden Nummer in der Rechnung macht keine zahlenmäßige Abfolge der ausgestellten Rechnungsnummern zwingend, da es lediglich um die Einmaligkeit der erteilten Rechnungsnummer geht. Die Anforderungen an die Rechnung sind vor dem Hintergrund zu interpretieren, dass es um die Verhinderung eines ungerechtfertigten Vorsteuerabzugs geht. Diesbezüglich reicht die Einmaligkeit der Nummerierung aus (Abschn. 185 Abs. 10 UStR).
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#20

AW: Vorgehensweise für Rechnungsnummernvergabe im Multi-User Betrieb

  Alt 28. Nov 2011, 11:18
Ich denke auch, dass es lediglich um die Eindeutigkeit einer Rechnungsnummer zu einem Vorgang geht, d.h. keine doppelten Rechnungsnummern o.ä. Fortlaufend müssen diese aber nicht zwingend sein. Man schaue sich nur mal z.B. die Rechnungen von Amazon an, dort wird eine Folge von (alpha-)numerischen Zeichen in Groß- und Kleinschreibung sowie Ziffern verwendet. Diese sind wohl eindeutig, aber fortlaufend wohl kaum...
Woher willst du wissen, dass diese NICHT fortlaufend sind? Kennst du die Nummerierungs-Regeln von amazon?
Gerade weil hier nicht nur mit Ziffern gearbeitet wird, ist es schwer dieses nachzuvollziehen, wenn man die Regel kennt, aber sehr wohl.

Der Hintergrund bei amazon ist aber wohl der, dass die Rechnungsnummern bei denen sehr schnell die Seitenbreite sprengen würden (bei der hohen Anzahl an Rechnungen) und daher haben die eben wohl ein 62er-ZahlenSystem (0..9,A..Z,a..z) genommen um relativ kurze Rechnungsnummern zu erhalten.

Zitat:
Ich hätte da mal eine Nachfrage zu einer Rechnung mit der Nummer 71...[halbe Stunde später]...68
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (28. Nov 2011 um 13:38 Uhr)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:46 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz