|
| 1 | +-- ============================================= |
| 2 | +-- Sales Operations Schema Enhancements |
| 3 | +-- Futon Manufacturing Database |
| 4 | +-- ============================================= |
| 5 | +-- Adds sales channel tracking, stores, and enhanced |
| 6 | +-- sales operations capabilities |
| 7 | +-- ============================================= |
| 8 | + |
| 9 | +USE FutonManufacturing; |
| 10 | +GO |
| 11 | + |
| 12 | +-- ============================================= |
| 13 | +-- Sales Channels and Stores |
| 14 | +-- ============================================= |
| 15 | + |
| 16 | +CREATE TABLE SalesChannel ( |
| 17 | + SalesChannelID INT IDENTITY(1,1) PRIMARY KEY, |
| 18 | + ChannelCode NVARCHAR(20) NOT NULL UNIQUE, |
| 19 | + ChannelName NVARCHAR(100) NOT NULL, |
| 20 | + Description NVARCHAR(255), |
| 21 | + IsActive BIT NOT NULL DEFAULT 1 |
| 22 | +); |
| 23 | + |
| 24 | +INSERT INTO SalesChannel (ChannelCode, ChannelName, Description) VALUES |
| 25 | +('RETAIL', 'Retail Store', 'Physical retail store sales'), |
| 26 | +('ONLINE', 'Online/E-Commerce', 'Online website and marketplace sales'), |
| 27 | +('WHOLESALE', 'Wholesale', 'Bulk sales to retailers and distributors'); |
| 28 | + |
| 29 | +CREATE TABLE Store ( |
| 30 | + StoreID INT IDENTITY(1,1) PRIMARY KEY, |
| 31 | + StoreCode NVARCHAR(20) NOT NULL UNIQUE, |
| 32 | + StoreName NVARCHAR(100) NOT NULL, |
| 33 | + SalesChannelID INT NOT NULL, |
| 34 | + Manager NVARCHAR(100), |
| 35 | + Phone NVARCHAR(20), |
| 36 | + Email NVARCHAR(100), |
| 37 | + Address NVARCHAR(255), |
| 38 | + City NVARCHAR(100), |
| 39 | + State NVARCHAR(50), |
| 40 | + ZipCode NVARCHAR(20), |
| 41 | + OpenDate DATE, |
| 42 | + IsActive BIT NOT NULL DEFAULT 1, |
| 43 | + CONSTRAINT FK_Store_SalesChannel FOREIGN KEY (SalesChannelID) REFERENCES SalesChannel(SalesChannelID) |
| 44 | +); |
| 45 | + |
| 46 | +CREATE TABLE SalesTerritory ( |
| 47 | + TerritoryID INT IDENTITY(1,1) PRIMARY KEY, |
| 48 | + TerritoryCode NVARCHAR(20) NOT NULL UNIQUE, |
| 49 | + TerritoryName NVARCHAR(100) NOT NULL, |
| 50 | + Region NVARCHAR(50), |
| 51 | + IsActive BIT NOT NULL DEFAULT 1 |
| 52 | +); |
| 53 | + |
| 54 | +CREATE TABLE SalesRep ( |
| 55 | + SalesRepID INT IDENTITY(1,1) PRIMARY KEY, |
| 56 | + EmployeeCode NVARCHAR(20) NOT NULL UNIQUE, |
| 57 | + FirstName NVARCHAR(50) NOT NULL, |
| 58 | + LastName NVARCHAR(50) NOT NULL, |
| 59 | + Email NVARCHAR(100), |
| 60 | + Phone NVARCHAR(20), |
| 61 | + TerritoryID INT, |
| 62 | + HireDate DATE, |
| 63 | + IsActive BIT NOT NULL DEFAULT 1, |
| 64 | + CONSTRAINT FK_SalesRep_Territory FOREIGN KEY (TerritoryID) REFERENCES SalesTerritory(TerritoryID) |
| 65 | +); |
| 66 | + |
| 67 | +-- ============================================= |
| 68 | +-- Enhance Existing Tables |
| 69 | +-- ============================================= |
| 70 | + |
| 71 | +-- Add sales channel tracking to SalesOrder |
| 72 | +ALTER TABLE SalesOrder ADD SalesChannelID INT NULL; |
| 73 | +ALTER TABLE SalesOrder ADD StoreID INT NULL; |
| 74 | +ALTER TABLE SalesOrder ADD SalesRepID INT NULL; |
| 75 | +ALTER TABLE SalesOrder ADD DiscountAmount DECIMAL(18,2) DEFAULT 0; |
| 76 | +ALTER TABLE SalesOrder ADD NetAmount AS (TotalAmount - DiscountAmount) PERSISTED; |
| 77 | + |
| 78 | +ALTER TABLE SalesOrder ADD CONSTRAINT FK_SalesOrder_SalesChannel |
| 79 | + FOREIGN KEY (SalesChannelID) REFERENCES SalesChannel(SalesChannelID); |
| 80 | +ALTER TABLE SalesOrder ADD CONSTRAINT FK_SalesOrder_Store |
| 81 | + FOREIGN KEY (StoreID) REFERENCES Store(StoreID); |
| 82 | +ALTER TABLE SalesOrder ADD CONSTRAINT FK_SalesOrder_SalesRep |
| 83 | + FOREIGN KEY (SalesRepID) REFERENCES SalesRep(SalesRepID); |
| 84 | + |
| 85 | +-- Add discount tracking to SalesOrderDetail |
| 86 | +ALTER TABLE SalesOrderDetail ADD DiscountPercent DECIMAL(5,2) DEFAULT 0; |
| 87 | +ALTER TABLE SalesOrderDetail ADD DiscountAmount AS (LineTotal * DiscountPercent / 100) PERSISTED; |
| 88 | +ALTER TABLE SalesOrderDetail ADD NetAmount AS (LineTotal - (LineTotal * DiscountPercent / 100)) PERSISTED; |
| 89 | + |
| 90 | +-- Add customer segmentation |
| 91 | +ALTER TABLE Customer ADD CustomerType NVARCHAR(20) DEFAULT 'Retail'; -- Retail, Wholesale, Online |
| 92 | +ALTER TABLE Customer ADD SalesRepID INT NULL; |
| 93 | +ALTER TABLE Customer ADD TerritoryID INT NULL; |
| 94 | + |
| 95 | +ALTER TABLE Customer ADD CONSTRAINT FK_Customer_SalesRep |
| 96 | + FOREIGN KEY (SalesRepID) REFERENCES SalesRep(SalesRepID); |
| 97 | +ALTER TABLE Customer ADD CONSTRAINT FK_Customer_Territory |
| 98 | + FOREIGN KEY (TerritoryID) REFERENCES SalesTerritory(TerritoryID); |
| 99 | + |
| 100 | +-- ============================================= |
| 101 | +-- Sales Returns and Exchanges |
| 102 | +-- ============================================= |
| 103 | + |
| 104 | +CREATE TABLE ReturnReason ( |
| 105 | + ReturnReasonID INT IDENTITY(1,1) PRIMARY KEY, |
| 106 | + ReasonCode NVARCHAR(20) NOT NULL UNIQUE, |
| 107 | + ReasonDescription NVARCHAR(255) NOT NULL, |
| 108 | + IsActive BIT NOT NULL DEFAULT 1 |
| 109 | +); |
| 110 | + |
| 111 | +INSERT INTO ReturnReason (ReasonCode, ReasonDescription) VALUES |
| 112 | +('DEFECT', 'Product defect or quality issue'), |
| 113 | +('DAMAGE', 'Damaged during shipping'), |
| 114 | +('WRONG', 'Wrong item received'), |
| 115 | +('NOFIT', 'Does not fit/wrong size'), |
| 116 | +('EXPECT', 'Did not meet expectations'), |
| 117 | +('CHANGE', 'Customer changed mind'), |
| 118 | +('LATE', 'Delivery too late'), |
| 119 | +('OTHER', 'Other reason'); |
| 120 | + |
| 121 | +CREATE TABLE SalesReturn ( |
| 122 | + ReturnID INT IDENTITY(1,1) PRIMARY KEY, |
| 123 | + ReturnNumber NVARCHAR(50) NOT NULL UNIQUE, |
| 124 | + SalesOrderID INT NOT NULL, |
| 125 | + CustomerID INT NOT NULL, |
| 126 | + ReturnDate DATE NOT NULL DEFAULT CAST(GETDATE() AS DATE), |
| 127 | + ReturnReasonID INT NOT NULL, |
| 128 | + Status NVARCHAR(20) NOT NULL DEFAULT 'Pending', -- Pending, Approved, Received, Refunded, Denied |
| 129 | + RefundAmount DECIMAL(18,2) DEFAULT 0, |
| 130 | + RestockingFee DECIMAL(18,2) DEFAULT 0, |
| 131 | + Notes NVARCHAR(MAX), |
| 132 | + ApprovedBy NVARCHAR(100), |
| 133 | + ApprovedDate DATETIME2, |
| 134 | + CreatedDate DATETIME2 DEFAULT GETDATE(), |
| 135 | + CONSTRAINT FK_Return_SalesOrder FOREIGN KEY (SalesOrderID) REFERENCES SalesOrder(SalesOrderID), |
| 136 | + CONSTRAINT FK_Return_Customer FOREIGN KEY (CustomerID) REFERENCES Customer(CustomerID), |
| 137 | + CONSTRAINT FK_Return_Reason FOREIGN KEY (ReturnReasonID) REFERENCES ReturnReason(ReturnReasonID) |
| 138 | +); |
| 139 | + |
| 140 | +CREATE TABLE SalesReturnDetail ( |
| 141 | + ReturnDetailID INT IDENTITY(1,1) PRIMARY KEY, |
| 142 | + ReturnID INT NOT NULL, |
| 143 | + SODetailID INT NOT NULL, |
| 144 | + ItemID INT NOT NULL, |
| 145 | + QuantityReturned DECIMAL(18,2) NOT NULL, |
| 146 | + UnitPrice DECIMAL(18,4) NOT NULL, |
| 147 | + RefundAmount DECIMAL(18,2) NOT NULL, |
| 148 | + Disposition NVARCHAR(50), -- Restock, Scrap, Repair, RMA |
| 149 | + CONSTRAINT FK_ReturnDetail_Return FOREIGN KEY (ReturnID) REFERENCES SalesReturn(ReturnID), |
| 150 | + CONSTRAINT FK_ReturnDetail_SODetail FOREIGN KEY (SODetailID) REFERENCES SalesOrderDetail(SODetailID), |
| 151 | + CONSTRAINT FK_ReturnDetail_Item FOREIGN KEY (ItemID) REFERENCES Items(ItemID) |
| 152 | +); |
| 153 | + |
| 154 | +-- ============================================= |
| 155 | +-- Sales Quotations |
| 156 | +-- ============================================= |
| 157 | + |
| 158 | +CREATE TABLE SalesQuote ( |
| 159 | + QuoteID INT IDENTITY(1,1) PRIMARY KEY, |
| 160 | + QuoteNumber NVARCHAR(50) NOT NULL UNIQUE, |
| 161 | + CustomerID INT NOT NULL, |
| 162 | + SalesChannelID INT, |
| 163 | + SalesRepID INT, |
| 164 | + QuoteDate DATE NOT NULL DEFAULT CAST(GETDATE() AS DATE), |
| 165 | + ExpirationDate DATE, |
| 166 | + Status NVARCHAR(20) NOT NULL DEFAULT 'Draft', -- Draft, Sent, Accepted, Declined, Expired |
| 167 | + Subtotal DECIMAL(18,2) DEFAULT 0, |
| 168 | + DiscountAmount DECIMAL(18,2) DEFAULT 0, |
| 169 | + TaxAmount DECIMAL(18,2) DEFAULT 0, |
| 170 | + TotalAmount DECIMAL(18,2) DEFAULT 0, |
| 171 | + ConvertedToOrderID INT NULL, |
| 172 | + Notes NVARCHAR(MAX), |
| 173 | + CreatedBy NVARCHAR(100), |
| 174 | + CreatedDate DATETIME2 DEFAULT GETDATE(), |
| 175 | + CONSTRAINT FK_Quote_Customer FOREIGN KEY (CustomerID) REFERENCES Customer(CustomerID), |
| 176 | + CONSTRAINT FK_Quote_SalesChannel FOREIGN KEY (SalesChannelID) REFERENCES SalesChannel(SalesChannelID), |
| 177 | + CONSTRAINT FK_Quote_SalesRep FOREIGN KEY (SalesRepID) REFERENCES SalesRep(SalesRepID), |
| 178 | + CONSTRAINT FK_Quote_ConvertedOrder FOREIGN KEY (ConvertedToOrderID) REFERENCES SalesOrder(SalesOrderID) |
| 179 | +); |
| 180 | + |
| 181 | +CREATE TABLE SalesQuoteDetail ( |
| 182 | + QuoteDetailID INT IDENTITY(1,1) PRIMARY KEY, |
| 183 | + QuoteID INT NOT NULL, |
| 184 | + LineNumber INT NOT NULL, |
| 185 | + ItemID INT NOT NULL, |
| 186 | + Quantity DECIMAL(18,2) NOT NULL, |
| 187 | + UnitPrice DECIMAL(18,4) NOT NULL, |
| 188 | + DiscountPercent DECIMAL(5,2) DEFAULT 0, |
| 189 | + LineTotal AS (Quantity * UnitPrice * (1 - DiscountPercent/100)) PERSISTED, |
| 190 | + CONSTRAINT FK_QuoteDetail_Quote FOREIGN KEY (QuoteID) REFERENCES SalesQuote(QuoteID), |
| 191 | + CONSTRAINT FK_QuoteDetail_Item FOREIGN KEY (ItemID) REFERENCES Items(ItemID) |
| 192 | +); |
| 193 | + |
| 194 | +-- ============================================= |
| 195 | +-- Promotions and Pricing |
| 196 | +-- ============================================= |
| 197 | + |
| 198 | +CREATE TABLE Promotion ( |
| 199 | + PromotionID INT IDENTITY(1,1) PRIMARY KEY, |
| 200 | + PromotionCode NVARCHAR(50) NOT NULL UNIQUE, |
| 201 | + PromotionName NVARCHAR(255) NOT NULL, |
| 202 | + Description NVARCHAR(MAX), |
| 203 | + DiscountPercent DECIMAL(5,2), |
| 204 | + DiscountAmount DECIMAL(18,2), |
| 205 | + StartDate DATE NOT NULL, |
| 206 | + EndDate DATE NOT NULL, |
| 207 | + IsActive BIT NOT NULL DEFAULT 1, |
| 208 | + MinimumPurchase DECIMAL(18,2) DEFAULT 0, |
| 209 | + ApplicableChannels NVARCHAR(255) -- CSV: RETAIL,ONLINE,WHOLESALE |
| 210 | +); |
| 211 | + |
| 212 | +CREATE TABLE PriceList ( |
| 213 | + PriceListID INT IDENTITY(1,1) PRIMARY KEY, |
| 214 | + PriceListCode NVARCHAR(20) NOT NULL UNIQUE, |
| 215 | + PriceListName NVARCHAR(100) NOT NULL, |
| 216 | + SalesChannelID INT, |
| 217 | + EffectiveDate DATE NOT NULL, |
| 218 | + EndDate DATE, |
| 219 | + IsActive BIT NOT NULL DEFAULT 1, |
| 220 | + CONSTRAINT FK_PriceList_SalesChannel FOREIGN KEY (SalesChannelID) REFERENCES SalesChannel(SalesChannelID) |
| 221 | +); |
| 222 | + |
| 223 | +CREATE TABLE PriceListDetail ( |
| 224 | + PriceListDetailID INT IDENTITY(1,1) PRIMARY KEY, |
| 225 | + PriceListID INT NOT NULL, |
| 226 | + ItemID INT NOT NULL, |
| 227 | + UnitPrice DECIMAL(18,4) NOT NULL, |
| 228 | + MinimumQuantity DECIMAL(18,2) DEFAULT 1, |
| 229 | + CONSTRAINT FK_PriceListDetail_PriceList FOREIGN KEY (PriceListID) REFERENCES PriceList(PriceListID), |
| 230 | + CONSTRAINT FK_PriceListDetail_Item FOREIGN KEY (ItemID) REFERENCES Items(ItemID) |
| 231 | +); |
| 232 | + |
| 233 | +-- ============================================= |
| 234 | +-- Indexes for Performance |
| 235 | +-- ============================================= |
| 236 | + |
| 237 | +CREATE NONCLUSTERED INDEX IX_SalesOrder_Channel ON SalesOrder(SalesChannelID, OrderDate); |
| 238 | +CREATE NONCLUSTERED INDEX IX_SalesOrder_Store ON SalesOrder(StoreID, OrderDate); |
| 239 | +CREATE NONCLUSTERED INDEX IX_SalesOrder_SalesRep ON SalesOrder(SalesRepID, OrderDate); |
| 240 | +CREATE NONCLUSTERED INDEX IX_Customer_Type ON Customer(CustomerType); |
| 241 | +CREATE NONCLUSTERED INDEX IX_SalesReturn_Date ON SalesReturn(ReturnDate); |
| 242 | +CREATE NONCLUSTERED INDEX IX_SalesQuote_Status ON SalesQuote(Status, QuoteDate); |
| 243 | + |
| 244 | +GO |
| 245 | + |
| 246 | +PRINT 'Sales operations schema enhancements completed successfully!'; |
| 247 | +GO |
0 commit comments