euler314 commited on
Commit
b8c9a2e
·
verified ·
1 Parent(s): 57fc3fb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -16
app.py CHANGED
@@ -34,20 +34,17 @@ def get_sheet_names():
34
  def ensure_headers(sheet_name):
35
  try:
36
  sheets_service = build('sheets', 'v4', credentials=CREDENTIALS)
37
-
38
  headers = [
39
- ['姓名 Name', '學號 Student ID', '購買商品 Product',
40
- '金額 Cost', '發票檔案 Receipt File', '時間 Timestamp', 'IP位址 IP Address']
41
  ]
42
 
43
  sheets_service.spreadsheets().values().update(
44
  spreadsheetId=SPREADSHEET_ID,
45
- range=f'{sheet_name}!A1:G1',
46
  valueInputOption='RAW',
47
  body={'values': headers}
48
  ).execute()
49
 
50
- # Format headers
51
  requests = [{
52
  'repeatCell': {
53
  'range': {
@@ -116,6 +113,10 @@ HTML_TEMPLATE = '''
116
  button:hover {
117
  background-color: #45a049;
118
  }
 
 
 
 
119
  #status {
120
  margin-top: 20px;
121
  padding: 15px;
@@ -139,10 +140,12 @@ HTML_TEMPLATE = '''
139
  .remove-person {
140
  background-color: #dc3545;
141
  margin-top: 10px;
 
142
  }
143
  #add-person {
144
  margin-bottom: 20px;
145
  background-color: #17a2b8;
 
146
  }
147
  .total-cost {
148
  font-size: 1.2em;
@@ -164,7 +167,7 @@ HTML_TEMPLATE = '''
164
  </div>
165
 
166
  <div class="form-group">
167
- <label for="product">購買商品 Product:</label>
168
  <input type="text" id="product" name="product" required>
169
  </div>
170
 
@@ -177,18 +180,19 @@ HTML_TEMPLATE = '''
177
  <!-- Person entries will be added here -->
178
  </div>
179
 
180
- <button type="button" id="add-person">新增人員 Add Person</button>
181
 
182
  <div class="total-cost">
183
  總金額 Total Cost: <span id="total">0</span>
184
  </div>
185
 
186
- <button type="submit">提交 Submit</button>
187
  </form>
188
  <div id="status"></div>
189
 
190
  <script>
191
  let personCounter = 0;
 
192
 
193
  function createPersonEntry() {
194
  const container = document.createElement('div');
@@ -223,12 +227,16 @@ HTML_TEMPLATE = '''
223
  function removePerson(button) {
224
  button.parentElement.remove();
225
  updateTotal();
 
226
  }
227
 
228
  document.getElementById('add-person').addEventListener('click', () => {
229
  const container = document.getElementById('people-container');
230
- container.appendChild(createPersonEntry());
231
- personCounter++;
 
 
 
232
  });
233
 
234
  // Add initial person entry
@@ -237,11 +245,16 @@ HTML_TEMPLATE = '''
237
  document.getElementById('purchaseForm').addEventListener('submit', async (e) => {
238
  e.preventDefault();
239
 
 
 
 
240
  if (document.getElementsByName('names[]').length === 0) {
241
- alert('請至少新增一個人員 Please add at least one person');
242
  return;
243
  }
244
 
 
 
245
  const status = document.getElementById('status');
246
  status.style.display = 'block';
247
  status.textContent = '提交中... Submitting...';
@@ -271,6 +284,8 @@ HTML_TEMPLATE = '''
271
  } catch (error) {
272
  status.className = 'error';
273
  status.textContent = '提交錯誤 Error submitting form';
 
 
274
  }
275
  });
276
  </script>
@@ -293,6 +308,15 @@ def submit():
293
  student_ids = request.form.getlist('studentIds[]')
294
  costs = request.form.getlist('costs[]')
295
 
 
 
 
 
 
 
 
 
 
296
  # Upload file to Drive
297
  drive_service = build('drive', 'v3', credentials=CREDENTIALS)
298
 
@@ -324,16 +348,21 @@ def submit():
324
  timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
325
  ip_address = request.remote_addr
326
 
327
- # Create entries for each person
328
- values = []
329
- for name, student_id, cost in zip(names, student_ids, costs):
330
- values.append([name, student_id, product, cost, file_url, timestamp, ip_address])
 
 
 
 
 
331
 
332
  body = {'values': values}
333
 
334
  sheets_service.spreadsheets().values().append(
335
  spreadsheetId=SPREADSHEET_ID,
336
- range=f'{sheet_name}!A:G',
337
  valueInputOption='USER_ENTERED',
338
  body=body
339
  ).execute()
 
34
  def ensure_headers(sheet_name):
35
  try:
36
  sheets_service = build('sheets', 'v4', credentials=CREDENTIALS)
 
37
  headers = [
38
+ ['項目 Item', '總金額 Total Cost', '發票檔案 Receipt File', '時間 Timestamp', 'IP位址 IP', '付款明細 Payment Details']
 
39
  ]
40
 
41
  sheets_service.spreadsheets().values().update(
42
  spreadsheetId=SPREADSHEET_ID,
43
+ range=f'{sheet_name}!A1:F1',
44
  valueInputOption='RAW',
45
  body={'values': headers}
46
  ).execute()
47
 
 
48
  requests = [{
49
  'repeatCell': {
50
  'range': {
 
113
  button:hover {
114
  background-color: #45a049;
115
  }
116
+ button:disabled {
117
+ background-color: #cccccc;
118
+ cursor: not-allowed;
119
+ }
120
  #status {
121
  margin-top: 20px;
122
  padding: 15px;
 
140
  .remove-person {
141
  background-color: #dc3545;
142
  margin-top: 10px;
143
+ width: auto;
144
  }
145
  #add-person {
146
  margin-bottom: 20px;
147
  background-color: #17a2b8;
148
+ width: auto;
149
  }
150
  .total-cost {
151
  font-size: 1.2em;
 
167
  </div>
168
 
169
  <div class="form-group">
170
+ <label for="product">購買項目 Item:</label>
171
  <input type="text" id="product" name="product" required>
172
  </div>
173
 
 
180
  <!-- Person entries will be added here -->
181
  </div>
182
 
183
+ <button type="button" id="add-person">新增付款人 Add Person</button>
184
 
185
  <div class="total-cost">
186
  總金額 Total Cost: <span id="total">0</span>
187
  </div>
188
 
189
+ <button type="submit" id="submitBtn">提交 Submit</button>
190
  </form>
191
  <div id="status"></div>
192
 
193
  <script>
194
  let personCounter = 0;
195
+ const maxPersons = 10; // Maximum number of persons allowed
196
 
197
  function createPersonEntry() {
198
  const container = document.createElement('div');
 
227
  function removePerson(button) {
228
  button.parentElement.remove();
229
  updateTotal();
230
+ document.getElementById('add-person').disabled = document.getElementsByClassName('person-entry').length >= maxPersons;
231
  }
232
 
233
  document.getElementById('add-person').addEventListener('click', () => {
234
  const container = document.getElementById('people-container');
235
+ if (container.children.length < maxPersons) {
236
+ container.appendChild(createPersonEntry());
237
+ personCounter++;
238
+ document.getElementById('add-person').disabled = container.children.length >= maxPersons;
239
+ }
240
  });
241
 
242
  // Add initial person entry
 
245
  document.getElementById('purchaseForm').addEventListener('submit', async (e) => {
246
  e.preventDefault();
247
 
248
+ const submitBtn = document.getElementById('submitBtn');
249
+ if (submitBtn.disabled) return;
250
+
251
  if (document.getElementsByName('names[]').length === 0) {
252
+ alert('請至少新增一個付款人 Please add at least one person');
253
  return;
254
  }
255
 
256
+ submitBtn.disabled = true;
257
+
258
  const status = document.getElementById('status');
259
  status.style.display = 'block';
260
  status.textContent = '提交中... Submitting...';
 
284
  } catch (error) {
285
  status.className = 'error';
286
  status.textContent = '提交錯誤 Error submitting form';
287
+ } finally {
288
+ submitBtn.disabled = false;
289
  }
290
  });
291
  </script>
 
308
  student_ids = request.form.getlist('studentIds[]')
309
  costs = request.form.getlist('costs[]')
310
 
311
+ # Calculate total
312
+ total_cost = sum(float(cost) for cost in costs)
313
+
314
+ # Create payment details string
315
+ payment_details = []
316
+ for name, student_id, cost in zip(names, student_ids, costs):
317
+ payment_details.append(f"{name}({student_id}): ${cost}")
318
+ payment_details_str = " | ".join(payment_details)
319
+
320
  # Upload file to Drive
321
  drive_service = build('drive', 'v3', credentials=CREDENTIALS)
322
 
 
348
  timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
349
  ip_address = request.remote_addr
350
 
351
+ # Create single row entry
352
+ values = [[
353
+ product,
354
+ total_cost,
355
+ file_url,
356
+ timestamp,
357
+ ip_address,
358
+ payment_details_str
359
+ ]]
360
 
361
  body = {'values': values}
362
 
363
  sheets_service.spreadsheets().values().append(
364
  spreadsheetId=SPREADSHEET_ID,
365
+ range=f'{sheet_name}!A:F',
366
  valueInputOption='USER_ENTERED',
367
  body=body
368
  ).execute()