web-dev-qa-db-fra.com

Schéma comptable à double entrée

Mettre en place un système de comptabilité à double entrée pour un usage personnel et pour aider à gérer une très petite entreprise. Essayer de mettre quelques fonctionnalités qui semblent pertinentes maintenant.

Règles d'entreprise

La logique, pour ceux qui ne connaissent pas la comptabilité, est: l'argent n'est pas créé ni détruit, il est seulement transféré d'un compte à un autre. Chaque transaction a un côté Débit et un côté Crédit. Quelques exemples:

  1. Salaire de votre employeur: crédit Salary, débit Bank Account - l'argent provenait de votre salaire et est allé sur votre compte bancaire.

  2. Paiement du loyer: crédit Bank Account, Débit Rent - l'argent est venu de votre compte bancaire et est allé sur votre compte de location.

Les comptes peuvent être des comptes "actions", dans le sens où le solde du compte est cumulatif (les comptes bancaires en sont un bon exemple) ou peuvent être des comptes de flux/flux, dans le sens où le solde du compte est non cumulatif (le loyer est un bon exemple).

La logique derrière la conception

L'idée est d'avoir une table JournalDB majeure qui stocke les entrées principales. La table JournalTx stocke chaque compte impliqué dans la transaction. Chaque entrée (de JournalDB) a un ID et chaque transaction (de JournalTx) est liée à une entrée de journal. Le scénario de base est qu'il y a 1 entrée sur JournalDB et deux (ou plus) transactions dans JournalTx. Chaque entrée peut avoir un cost_center, un project et quelques autres attributs.

Il y a essentiellement deux façons de concevoir cela (selon cette question ) - comme une ligne par style de transaction et deux lignes par transaction. Dans le premier, j'aurais une ligne avec le compte de crédit et le compte de débit, sur le second (celui-ci) il y a n lignes, une pour chaque compte affecté.

Comptes

Le tableau des comptes est le plan comptable (dans le jargon comptable). Is a une structure hiérarchique - j'ai utilisé le style de liste d'adjacence. Bien que peu fréquents, les comptes auront des opérations CRUD. J'ai ajouté parent_imediate, parent_second comme une solution vraiment moche pour faire des agrégations (calculer le total du compte des actifs, par exemple), mais étant donné le défi (je n'ai aucune idée de comment le faire après une longue recherche), cela semblait être une solution facile - tout toute contribution ou suggestion à ce sujet est également la bienvenue.

Requêtes principales

Obtenez les rapports, généralement tous les mois: en gros tous les comptes avec les transactions agrégées qui ont affecté chacun d'entre eux. Le meilleur scénario serait celui d'un tableau croisé dynamique (colonnes en tant que dates), chaque ligne étant un compte. Je suppose qu'une version "empilée" de cela fonctionnerait très bien aussi.

Les comptes ne sont qu'une dimension - je souhaiterais peut-être interroger par cost_center ou par project par exemple.

Autres caractéristiques

Je veux avoir la capacité de budgéter les comptes (d'où le tableau des budgets), ainsi que d'avoir des "objectifs" (je veux prendre des vacances qui me coûteront 1 000 $). Je souhaite également disposer de tags et pouvoir configurer des factures récurrentes (qui sont des transactions "attendues")

Relations de base

Une entrée (journal_db) comporte de nombreuses transactions (journal_tx). Un centre de coûts, un projet, etc. ont de nombreuses entrées Un compte a de nombreuses transactions. Un contact a plusieurs entrées.

enter image description here

Mes principaux doutes

Je commence tout juste à en apprendre davantage sur la DB/programmation, alors soyez indulgents avec moi pour les erreurs évidentes.

  1. Cette conception est-elle solide d'un point de vue programmation/performance/fonctionnalité?
  2. Comment implémenter le reporting? Interroger la base de données (table dérivée) ou créer une nouvelle table (comme journal_reports) et créer des déclencheurs pour mettre à jour les soldes des comptes pour chaque entrée? (lire cette question ce n'est pas une si bonne idée)
  3. Quelque chose que je pourrais manquer?
9
lowercase00

Je pense que votre question est assez large et difficile à répondre dans son intégralité. Mais voici quelques choses que j'ai remarquées sur votre design:

Conception générale

Certaines tables de votre conception violent la première forme normale. Un bon exemple est contact_adress qui a adress1, adress2 et adress3 sous forme de colonnes. Habituellement, un lieu n'a qu'une seule adresse et une colonne d'adresses suffit, mais si vous voulez vraiment avoir la possibilité d'ajouter plusieurs adresses à un endroit, vous devez déplacer ces adresses vers une autre table (contact_adress, street_adress). Il en va de même pour journal_bills (detail1, detail2) et la table accounts: au lieu de parent_imediate, parent_second et parent_third un seul attribut parent devrait suffire. Pour obtenir le deuxième ou le troisième parent, vous pouvez utiliser CTE récursif à la place.

Je ne connais pas toutes vos exigences commerciales, mais vous devriez vérifier si votre conception vous permet d'entrer des données absurdes: un compte peut-il être à la fois en espèces et en crédit? Si vous avez des devises, quels sont les taux de change? Un code postal peut-il commencer par un ou plusieurs zéros? Et les numéros de téléphone? Pour certaines choses, il existe des meilleures pratiques, par exemple comment gérer les événements récurrents .

Appellation

Certains noms de colonne sont difficiles à comprendre (ag, acc, pmt), ce qui peut entraîner des problèmes de maintenabilité si quelqu'un d'autre doit travailler avec votre base de données. Utilisez un guide de style si vous ne savez pas comment nommer les choses. Généralement, c'est une bonne idée de s'en tenir à un schéma de dénomination cohérent, par ex. donnez à chaque table un nom pluriel.

Comment implémenter le reporting?

Je m'en tenir aux requêtes SQL simples et essayer de rester à l'écart des fonctions sophistiquées comme les déclencheurs, sauf si vous en avez vraiment besoin, ce qui n'est probablement jamais le cas pour une application simple.

1
taffer