ZeeAI1 commited on
Commit
8568540
·
verified ·
1 Parent(s): f31749a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +128 -58
app.py CHANGED
@@ -4,10 +4,15 @@ from transformers import AutoModelForCausalLM, AutoTokenizer
4
  import uuid
5
  import datetime
6
 
7
- # Initialize AI model (Mistral-7B)
8
  model_name = "mistralai/Mixtral-8x7B-Instruct-v0.1"
9
- tokenizer = AutoTokenizer.from_pretrained(model_name)
10
- model = AutoModelForCausalLM.from_pretrained(model_name)
 
 
 
 
 
11
 
12
  # Database setup
13
  conn = sqlite3.connect("erp.db")
@@ -17,21 +22,24 @@ cursor = conn.cursor()
17
  cursor.execute("""
18
  CREATE TABLE IF NOT EXISTS chart_of_accounts (
19
  account_id TEXT PRIMARY KEY,
20
- account_name TEXT,
21
- account_type TEXT,
22
  parent_id TEXT,
23
  allow_budgeting BOOLEAN,
24
- allow_posting BOOLEAN
 
25
  )
26
  """)
27
  cursor.execute("""
28
  CREATE TABLE IF NOT EXISTS journal_entries (
29
  entry_id TEXT PRIMARY KEY,
30
- date TEXT,
31
- debit_account_id TEXT,
32
- credit_account_id TEXT,
33
- amount REAL,
34
- description TEXT
 
 
35
  )
36
  """)
37
  conn.commit()
@@ -45,14 +53,25 @@ ACCOUNT_RULES = {
45
  "Expense": {"increase": "Debit", "decrease": "Credit"}
46
  }
47
 
48
- # Sample chart of accounts
49
  def initialize_chart_of_accounts():
50
  accounts = [
51
- ("1", "Fixed Assets", "Asset", None, True, False),
52
- ("1.1", "Plant", "Asset", "1", True, True),
53
- ("1.2", "Machinery", "Asset", "1", True, True),
54
- ("2", "Cash", "Asset", None, True, True),
55
- ("3", "Accounts Payable", "Liability", None, True, True)
 
 
 
 
 
 
 
 
 
 
 
56
  ]
57
  cursor.executemany("""
58
  INSERT OR REPLACE INTO chart_of_accounts
@@ -61,61 +80,103 @@ def initialize_chart_of_accounts():
61
  """, accounts)
62
  conn.commit()
63
 
64
- # Parse prompt using AI model
65
  def parse_prompt(prompt):
66
- input_text = f"Parse the following accounting prompt and return a JSON object with debit and credit accounts, amount, and payment method (cash or credit). Prompt: {prompt}"
67
- inputs = tokenizer(input_text, return_tensors="pt")
68
- outputs = model.generate(**inputs, max_length=200)
69
- response = tokenizer.decode(outputs[0], skip_special_tokens=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
- # Assume model returns JSON-like string
72
- try:
73
- parsed = json.loads(response)
74
- return parsed
75
- except:
76
- # Fallback parsing
77
- if "laptop" in prompt.lower() and "cash" in prompt.lower():
78
- return {
79
- "debit": {"account": "Laptop", "type": "Asset", "amount": 200},
80
- "credit": {"account": "Cash", "type": "Asset", "amount": 200},
81
- "payment_method": "cash"
82
- }
83
  return None
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  # Generate journal entry
86
  def generate_journal_entry(prompt, follow_up_response=None):
87
  parsed = parse_prompt(prompt)
88
  if not parsed:
89
- return "Unable to parse prompt. Please clarify."
90
 
91
  debit_account = parsed["debit"]["account"]
92
- credit_account = parsed["credit"]["account"]
93
  amount = parsed["debit"]["amount"]
94
  payment_method = parsed.get("payment_method")
95
 
96
- # Follow-up for payment method
97
- if not payment_method:
98
- return "Wonderful, did you buy on credit? (Yes/No)"
99
 
100
- # Adjust credit account for credit purchases
 
 
101
  if follow_up_response and follow_up_response.lower() == "yes":
102
  credit_account = "Accounts Payable"
103
  credit_type = "Liability"
104
- else:
 
105
  credit_type = parsed["credit"]["type"]
 
 
 
 
 
106
 
107
- # Find account IDs
108
- cursor.execute("SELECT account_id, allow_posting FROM chart_of_accounts WHERE account_name = ?", (debit_account,))
109
  debit_result = cursor.fetchone()
110
- cursor.execute("SELECT account_id, allow_posting FROM chart_of_accounts WHERE account_name = ?", (credit_account,))
111
  credit_result = cursor.fetchone()
112
 
113
  if not debit_result or not credit_result:
114
- return "Invalid account names."
115
- if not debit_result[1] or not credit_result[1]:
116
  return "Posting not allowed for one or both accounts."
117
 
118
- # Save journal entry
 
 
 
 
119
  entry_id = str(uuid.uuid4())
120
  date = datetime.datetime.now().isoformat()
121
  cursor.execute("""
@@ -138,15 +199,21 @@ def generate_t_account(account_name):
138
  SELECT amount, description, 'Debit' as type FROM journal_entries WHERE debit_account_id = ?
139
  UNION
140
  SELECT amount, description, 'Credit' as type FROM journal_entries WHERE credit_account_id = ?
 
141
  """, (account_id, account_id))
142
  entries = cursor.fetchall()
143
 
144
- t_account = f"T-Account for {account_name}\n{'-'*40}\nDebit | Credit\n{'-'*40}\n"
 
 
145
  for amount, desc, entry_type in entries:
146
  if entry_type == "Debit":
147
- t_account += f"${amount} | | {desc}\n"
 
148
  else:
149
- t_account += f" | ${amount} | {desc}\n"
 
 
150
 
151
  return t_account
152
 
@@ -154,19 +221,22 @@ def generate_t_account(account_name):
154
  if __name__ == "__main__":
155
  initialize_chart_of_accounts()
156
 
157
- # Test prompt
158
  prompt = "Bought a laptop for $200 on cash"
159
  result = generate_journal_entry(prompt)
160
  print(result)
161
 
 
 
 
 
 
 
 
 
162
  # Test T-account
163
  t_account = generate_t_account("Laptop")
164
  print(t_account)
165
 
166
- # Test follow-up
167
- prompt = "Bought a laptop for $200"
168
- result = generate_journal_entry(prompt)
169
- print(result)
170
- if "did you buy on credit" in result.lower():
171
- result = generate_journal_entry(prompt, "Yes")
172
- print(result)
 
4
  import uuid
5
  import datetime
6
 
7
+ # Initialize AI model (Mistral-7B placeholder; replace with actual model)
8
  model_name = "mistralai/Mixtral-8x7B-Instruct-v0.1"
9
+ try:
10
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
11
+ model = AutoModelForCausalLM.from_pretrained(model_name)
12
+ except:
13
+ # Fallback for demo (mock AI response)
14
+ tokenizer = None
15
+ model = None
16
 
17
  # Database setup
18
  conn = sqlite3.connect("erp.db")
 
22
  cursor.execute("""
23
  CREATE TABLE IF NOT EXISTS chart_of_accounts (
24
  account_id TEXT PRIMARY KEY,
25
+ account_name TEXT NOT NULL,
26
+ account_type TEXT NOT NULL,
27
  parent_id TEXT,
28
  allow_budgeting BOOLEAN,
29
+ allow_posting BOOLEAN,
30
+ FOREIGN KEY (parent_id) REFERENCES chart_of_accounts(account_id)
31
  )
32
  """)
33
  cursor.execute("""
34
  CREATE TABLE IF NOT EXISTS journal_entries (
35
  entry_id TEXT PRIMARY KEY,
36
+ date TEXT NOT NULL,
37
+ debit_account_id TEXT NOT NULL,
38
+ credit_account_id TEXT NOT NULL,
39
+ amount REAL NOT NULL,
40
+ description TEXT,
41
+ FOREIGN KEY (debit_account_id) REFERENCES chart_of_accounts(account_id),
42
+ FOREIGN KEY (credit_account_id) REFERENCES chart_of_accounts(account_id)
43
  )
44
  """)
45
  conn.commit()
 
53
  "Expense": {"increase": "Debit", "decrease": "Credit"}
54
  }
55
 
56
+ # Initialize chart of accounts
57
  def initialize_chart_of_accounts():
58
  accounts = [
59
+ ("1", "Assets", "Asset", None, True, False),
60
+ ("1.1", "Fixed Assets", "Asset", "1", True, False),
61
+ ("1.1.1", "Plant", "Asset", "1.1", True, True),
62
+ ("1.1.2", "Machinery", "Asset", "1.1", True, True),
63
+ ("1.1.3", "Building", "Asset", "1.1", True, True),
64
+ ("1.2", "Current Assets", "Asset", "1", True, False),
65
+ ("1.2.1", "Cash", "Asset", "1.2", True, True),
66
+ ("1.2.2", "Laptop", "Asset", "1.2", True, True),
67
+ ("2", "Liabilities", "Liability", None, True, False),
68
+ ("2.1", "Accounts Payable", "Liability", "2", True, True),
69
+ ("3", "Equity", "Equity", None, True, False),
70
+ ("3.1", "Owner's Capital", "Equity", "3", True, True),
71
+ ("4", "Revenue", "Revenue", None, True, False),
72
+ ("4.1", "Sales", "Revenue", "4", True, True),
73
+ ("5", "Expenses", "Expense", None, True, False),
74
+ ("5.1", "Operating Expenses", "Expense", "5", True, True)
75
  ]
76
  cursor.executemany("""
77
  INSERT OR REPLACE INTO chart_of_accounts
 
80
  """, accounts)
81
  conn.commit()
82
 
83
+ # Parse prompt using AI model (or fallback)
84
  def parse_prompt(prompt):
85
+ if model and tokenizer:
86
+ input_text = f"""
87
+ Parse the following accounting prompt into a JSON object with:
88
+ - debit: {account, type, amount}
89
+ - credit: {account, type, amount}
90
+ - payment_method: 'cash' or 'credit' or null
91
+ Prompt: {prompt}
92
+ """
93
+ inputs = tokenizer(input_text, return_tensors="pt")
94
+ outputs = model.generate(**inputs, max_length=300)
95
+ response = tokenizer.decode(outputs[0], skip_special_tokens=True)
96
+ try:
97
+ return json.loads(response)
98
+ except:
99
+ pass
100
+
101
+ # Fallback parsing for common scenarios
102
+ prompt_lower = prompt.lower()
103
+ amount = None
104
+ for word in prompt_lower.split():
105
+ if word.startswith("$"):
106
+ try:
107
+ amount = float(word[1:])
108
+ break
109
+ except:
110
+ pass
111
 
112
+ if not amount:
 
 
 
 
 
 
 
 
 
 
 
113
  return None
114
 
115
+ if "laptop" in prompt_lower:
116
+ debit_account = "Laptop"
117
+ debit_type = "Asset"
118
+ if "cash" in prompt_lower:
119
+ credit_account = "Cash"
120
+ credit_type = "Asset"
121
+ payment_method = "cash"
122
+ elif "credit" in prompt_lower:
123
+ credit_account = "Accounts Payable"
124
+ credit_type = "Liability"
125
+ payment_method = "credit"
126
+ else:
127
+ return {"debit": {"account": "Laptop", "type": "Asset", "amount": amount}, "credit": None, "payment_method": None}
128
+ return {
129
+ "debit": {"account": debit_account, "type": debit_type, "amount": amount},
130
+ "credit": {"account": credit_account, "type": credit_type, "amount": amount},
131
+ "payment_method": payment_method
132
+ }
133
+ return None
134
+
135
  # Generate journal entry
136
  def generate_journal_entry(prompt, follow_up_response=None):
137
  parsed = parse_prompt(prompt)
138
  if not parsed:
139
+ return "Unable to parse prompt. Please provide more details."
140
 
141
  debit_account = parsed["debit"]["account"]
 
142
  amount = parsed["debit"]["amount"]
143
  payment_method = parsed.get("payment_method")
144
 
145
+ # Handle ambiguous payment method
146
+ if not payment_method and not follow_up_response:
147
+ return {"status": "clarify", "message": "Wonderful, did you buy on credit? (Yes/No)"}
148
 
149
+ # Determine credit account
150
+ credit_account = None
151
+ credit_type = None
152
  if follow_up_response and follow_up_response.lower() == "yes":
153
  credit_account = "Accounts Payable"
154
  credit_type = "Liability"
155
+ elif payment_method == "cash":
156
+ credit_account = parsed["credit"]["account"]
157
  credit_type = parsed["credit"]["type"]
158
+ elif payment_method == "credit":
159
+ credit_account = "Accounts Payable"
160
+ credit_type = "Liability"
161
+ else:
162
+ return "Invalid payment method specified."
163
 
164
+ # Validate accounts
165
+ cursor.execute("SELECT account_id, account_type, allow_posting FROM chart_of_accounts WHERE account_name = ?", (debit_account,))
166
  debit_result = cursor.fetchone()
167
+ cursor.execute("SELECT account_id, account_type, allow_posting FROM chart_of_accounts WHERE account_name = ?", (credit_account,))
168
  credit_result = cursor.fetchone()
169
 
170
  if not debit_result or not credit_result:
171
+ return "One or both accounts not found in chart of accounts."
172
+ if not debit_result[2] or not credit_result[2]:
173
  return "Posting not allowed for one or both accounts."
174
 
175
+ # Validate account types
176
+ if debit_result[1] != parsed["debit"]["type"] or credit_result[1] != credit_type:
177
+ return "Account type mismatch."
178
+
179
+ # Create journal entry
180
  entry_id = str(uuid.uuid4())
181
  date = datetime.datetime.now().isoformat()
182
  cursor.execute("""
 
199
  SELECT amount, description, 'Debit' as type FROM journal_entries WHERE debit_account_id = ?
200
  UNION
201
  SELECT amount, description, 'Credit' as type FROM journal_entries WHERE credit_account_id = ?
202
+ ORDER BY date
203
  """, (account_id, account_id))
204
  entries = cursor.fetchall()
205
 
206
+ t_account = f"T-Account for {account_name}\n{'='*50}\n{'Debit':<20} | {'Credit':<20} | Description\n{'-'*50}\n"
207
+ debit_total = 0
208
+ credit_total = 0
209
  for amount, desc, entry_type in entries:
210
  if entry_type == "Debit":
211
+ t_account += f"${amount:<19} | {'':<20} | {desc}\n"
212
+ debit_total += amount
213
  else:
214
+ t_account += f"{'':<20} | ${amount:<19} | {desc}\n"
215
+ credit_total += amount
216
+ t_account += f"{'-'*50}\nTotal Debit: ${debit_total:<10} | Total Credit: ${credit_total}\n"
217
 
218
  return t_account
219
 
 
221
  if __name__ == "__main__":
222
  initialize_chart_of_accounts()
223
 
224
+ # Test prompt (cash purchase)
225
  prompt = "Bought a laptop for $200 on cash"
226
  result = generate_journal_entry(prompt)
227
  print(result)
228
 
229
+ # Test prompt (ambiguous payment method)
230
+ prompt = "Bought a laptop for $300"
231
+ result = generate_journal_entry(prompt)
232
+ print(result)
233
+ if isinstance(result, dict) and result["status"] == "clarify":
234
+ result = generate_journal_entry(prompt, "Yes")
235
+ print(result)
236
+
237
  # Test T-account
238
  t_account = generate_t_account("Laptop")
239
  print(t_account)
240
 
241
+ # Clean up
242
+ conn.close()