Mon conseil à environ 4 ans d'avoir à travailler avec le back-end d'un système de facturation que quelqu'un d'autre conçu: vous N'avez pas un état "en attente" sur les factures. Il va vous conduire fou.
Le problème avec l'enregistrement des factures ordinaires factures (avec un "en attente" drapeau de l'état/) c'est qu'il y aura des centaines d'opérations/les rapports qui sont censés prendre en compte posté factures, qui signifie littéralement chaque état , sauf pour l'attente. Ce qui signifie que cet état doit être vérifié tous les. unique. temps. Et quelqu'un va l'oublier. Et il en sera de semaines avant que quelqu'un s'en rend compte.
Vous pouvez créer un ActiveInvoices
vue avec l'attente de filtre intégré, mais qui déplace simplement le problème, quelqu'un en aura oubliez pas d'utiliser la vue au lieu de la table.
En attente de la facture n'est pas une facture. Il est bien dit dans la question des commentaires comme un projet (ou un ordre, une demande, etc., tous le même concept). Le besoin d'être en mesure de modifier ces projets est compréhensible, certainement. Voici donc ma recommandation.
Tout d'abord, créez un projet de table (que nous appellerons Orders
):
CREATE TABLE Orders
(
OrderID int NOT NULL IDENTITY(1, 1)
CONSTRAINT PK_Orders PRIMARY KEY CLUSTERED,
OrderDate datetime NOT NULL
CONSTRAINT DF_Orders_OrderDate DEFAULT GETDATE(),
OrderStatus tinyint NOT NULL, -- 0 = Active, 1 = Canceled, 2 = Invoiced
...
)
CREATE TABLE OrderDetails
(
-- Optional, if individual details need to be referenced
OrderDetailID int NOT NULL IDENTITY(1, 1)
CONSTRAINT PK_OrderDetails PRIMARY KEY CLUSTERED,
OrderID int NOT NULL
CONSTRAINT FK_OrderDetails_Orders FOREIGN KEY
REFERENCES Orders (OrderID)
ON UPDATE CASCADE
ON DELETE CASCADE,
...
)
CREATE INDEX IX_OrderDetails
ON OrderDetails (OrderID)
INCLUDE (...)
Ce sont de base de votre "projet" des tables. Ils peuvent être modifiés. Pour suivre les modifications, vous devez créer l'histoire des tableaux, dont toutes les colonnes qui sont à l'origine, Orders
et OrderDetails
tables, en plus de la vérification des colonnes de la dernière modification de l'utilisateur, la date et le type de modification (insert, update ou delete).
Comme Cade mentionne, vous pouvez utiliser AutoAudit pour automatiser la plupart de ces processus.
Ce que vous voudrez également un déclencheur pour prévenir des mises à jour pour les projets qui ne sont plus actifs (en particulier les projets qui sont affichés, et sont devenus des factures). Il est important de garder ces données cohérentes:
CREATE TRIGGER tr_Orders_ActiveUpdatesOnly
ON Orders
FOR UPDATE, DELETE
AS
IF EXISTS
(
SELECT 1
FROM deleted
WHERE OrderStatus <> 0
)
BEGIN
RAISERROR('Cannot modify a posted/canceled order.', 16, 1)
ROLLBACK
END
Car les factures sont une hiérarchie à deux niveaux, vous avez besoin d'un semblable et un peu plus compliqué de déclenchement pour les détails:
CREATE TRIGGER tr_OrderDetails_ActiveUpdatesOnly
ON OrderDetails
FOR INSERT, UPDATE, DELETE
AS
IF EXISTS
(
SELECT 1
FROM
(
SELECT OrderID FROM deleted
UNION ALL
SELECT OrderID FROM inserted
) d
INNER JOIN Orders o
ON o.OrderID = d.OrderID
WHERE o.OrderStatus <> 0
)
BEGIN
RAISERROR('Cannot change details for a posted/canceled order.', 16, 1)
ROLLBACK
END
Cela peut sembler beaucoup de travail, mais maintenant vous pouvez faire ceci:
CREATE TABLE Invoices
(
InvoiceID int NOT NULL IDENTITY(1, 1)
CONSTRAINT PK_Invoices PRIMARY KEY CLUSTERED,
OrderID int NOT NULL
CONSTRAINT FK_Invoices_Orders FOREIGN KEY
REFERENCES Orders (OrderID),
InvoiceDate datetime NOT NULL
CONSTRAINT DF_Invoices_Date DEFAULT GETDATE(),
IsPaid bit NOT NULL
CONSTRAINT DF_Invoices_IsPaid DEFAULT 0,
...
)
Voir ce que j'ai fait ici? Nos factures sont vierges, sacré entités des nations unies-entachée par les changements arbitraires par quelques-premier-jour-sur-le-emploi de service à la clientèle gars. Il n'y a pas de risque de vissage jusqu'ici. Mais, si nous en avons besoin, nous pouvons encore trouver de l'ensemble de "l'histoire" d'une facture, car il des liens de retour à son origine, en Order
- ce qui, si vous vous souvenez, nous ne sommes pas la possibilité de changer de après avoir quitté le statut de membre actif.
Cela représente correctement ce qui se passe dans le monde réel. Une fois qu'une facture est envoyée/posté, il ne peut pas être repris. C'est là-bas. Si vous souhaitez annuler, vous devez poster un renversement, soit pour un A/R (si votre système prend en charge ce genre de chose) ou comme un négatif de la facture pour satisfaire votre information financière. Et si cela est fait, vous pouvez réellement voir ce qui s'est passé , sans avoir à fouiller dans l'historique d'audit pour chaque facture; vous avez juste à regarder les factures elles-mêmes.
Il y a toujours le problème que les développeurs n'oubliez pas de modifier le statut de la commande après qu'il a été publié comme une facture, mais nous pouvons remédier à cela avec un déclencheur:
CREATE TRIGGER tr_Invoices_UpdateOrderStatus
ON Invoices
FOR INSERT
AS
UPDATE Orders
SET OrderStatus = 2
WHERE OrderID IN (SELECT OrderID FROM inserted)
Maintenant, vos données sont en sécurité à cause de utilisateurs et même imprudent de développeurs. Et les factures ne sont plus ambigus; vous n'avez pas à vous soucier des bugs rampant parce que quelqu'un a oublié de vérifier le statut de la facture, parce qu'il n'y est pas de statut.
Donc, juste pour re-résumer et paraphraser certains de ceci: Pourquoi ai-je pris cette peine, juste pour quelques la facture de l'histoire?
Parce que les factures qui n'ont pas été publiés mais ne sont pas des transactions réelles. Ils sont des transactions "état" - les opérations en cours. Ils n'appartiennent pas avec vos données transactionnelles. En les gardant séparées comme ceci, vous permettra de résoudre beaucoup de potentiel de futurs problèmes.
Avertissement: C'est tout en parlant de mon expérience personnelle et je n'ai pas vu tous les système de facturation dans le monde. Je ne peux pas garantir avec certitude à 100% que c'est approprié pour votre application particulière. Je ne peux que réitérer le nid de guêpes problèmes que j'ai vu résultant de la notion de "en attente", factures, à partir d'un mélange de l'état des données avec les données transactionnelles.
Comme avec tous les autres que vous trouverez sur l'internet, vous devez étudier cela comme une option possible et d'évaluer si oui ou non il peut vraiment travailler pour vous.