@@ -185,6 +185,284 @@ def handle_bad_request(err):
185
185
@app .route ('/healthz' )
186
186
def healthz ():
187
187
return jsonify ({'status' : 'ok' })
188
+ from flask import Flask , request , jsonify
189
+ from werkzeug .exceptions import BadRequest
190
+ from flask_cors import CORS
191
+
192
+ app = Flask (__name__ )
193
+ CORS (app )
194
+
195
+
196
+ # In-memory data store for employees (for demo purposes)
197
+ employees = {
198
+ 'E001' : {
199
+ 'id' : 'E001' ,
200
+ 'name' : 'John Doe' ,
201
+
202
+ 'phone' : '123-456-7890' ,
203
+ 'title' : 'Software Engineer' ,
204
+ 'department' : 'Engineering' ,
205
+ 'salary' : 5000 ,
206
+ 'status' : 'active' ,
207
+ },
208
+ 'E002' : {
209
+ 'id' : 'E002' ,
210
+ 'name' : 'Jane Smith' ,
211
+
212
+ 'phone' : '987-654-3210' ,
213
+ 'title' : 'Product Manager' ,
214
+ 'department' : 'Product' ,
215
+ 'salary' : 6500 ,
216
+ 'status' : 'active' ,
217
+ },
218
+ }
219
+
220
+
221
+ # 1. GPS定位
222
+ @app .route ('/gps' , methods = ['GET' ])
223
+ def get_location ():
224
+ # 这里需要调用GPS定位的API,获取用户的经纬度信息
225
+ # 由于GPS定位需要在移动设备上才能实现,这里我们只返回一个模拟数据
226
+ location = {'latitude' : 31.2304 , 'longitude' : 121.4737 }
227
+ return jsonify (location )
228
+
229
+
230
+ # 2. EPF (Employee Provident Fund) 公积金计算
231
+ @app .route ('/epf' , methods = ['POST' ])
232
+ def calculate_epf ():
233
+ data = request .get_json (silent = True ) or {}
234
+ if 'salary' not in data :
235
+ raise BadRequest ('Missing field: salary' )
236
+ try :
237
+ salary = float (data .get ('salary' ))
238
+ except (TypeError , ValueError ):
239
+ raise BadRequest ('Invalid salary' )
240
+
241
+ # EPF的计算逻辑,这里假设员工和雇主各缴纳11%和13%
242
+ employee_contribution = round (salary * 0.11 , 2 )
243
+ employer_contribution = round (salary * 0.13 , 2 )
244
+ total_contribution = round (employee_contribution + employer_contribution , 2 )
245
+ return jsonify ({
246
+ 'employee_contribution' : employee_contribution ,
247
+ 'employer_contribution' : employer_contribution ,
248
+ 'total_contribution' : total_contribution
249
+ })
250
+
251
+
252
+ # 3. PERKESO (Social Security Organization) 社险计算
253
+ @app .route ('/perkeso' , methods = ['POST' ])
254
+ def calculate_perkeso ():
255
+ data = request .get_json (silent = True ) or {}
256
+ if 'salary' not in data :
257
+ raise BadRequest ('Missing field: salary' )
258
+ try :
259
+ salary = float (data .get ('salary' ))
260
+ except (TypeError , ValueError ):
261
+ raise BadRequest ('Invalid salary' )
262
+
263
+ # PERKESO的计算逻辑,具体费率需要参考官方数据
264
+ employee_contribution = round (salary * 0.005 , 2 )
265
+ employer_contribution = round (salary * 0.01 , 2 )
266
+ total_contribution = round (employee_contribution + employer_contribution , 2 )
267
+ return jsonify ({
268
+ 'employee_contribution' : employee_contribution ,
269
+ 'employer_contribution' : employer_contribution ,
270
+ 'total_contribution' : total_contribution
271
+ })
272
+
273
+
274
+ # 4. PCB (Potongan Cukai Bulanan) 月度所得税计算
275
+ @app .route ('/pcb' , methods = ['POST' ])
276
+ def calculate_pcb ():
277
+ data = request .get_json (silent = True ) or {}
278
+ if 'salary' not in data :
279
+ raise BadRequest ('Missing field: salary' )
280
+ try :
281
+ salary = float (data .get ('salary' ))
282
+ except (TypeError , ValueError ):
283
+ raise BadRequest ('Invalid salary' )
284
+
285
+ # PCB的计算逻辑非常复杂,需要参考LHDN的官方指南
286
+ # 这里我们只返回一个模拟数据
287
+ pcb = round (salary * 0.1 , 2 )
288
+ return jsonify ({'pcb' : pcb })
289
+
290
+
291
+ # 5. 打卡功能
292
+ @app .route ('/clock_in' , methods = ['POST' ])
293
+ def clock_in ():
294
+ data = request .get_json (silent = True ) or {}
295
+ employee_id = data .get ('employee_id' )
296
+ if not employee_id :
297
+ raise BadRequest ('Missing field: employee_id' )
298
+ # 这里需要记录打卡的时间和地点
299
+ return jsonify ({'message' : 'Clock in successful' })
300
+
301
+
302
+ # 6. 考勤表
303
+ @app .route ('/attendance' , methods = ['GET' ])
304
+ def get_attendance ():
305
+ employee_id = request .args .get ('employee_id' )
306
+ if not employee_id :
307
+ raise BadRequest ('Missing query param: employee_id' )
308
+ # 这里需要从数据库中查询考勤记录
309
+ attendance_records = [
310
+ {'date' : '2023-11-01' , 'clock_in' : '09:00' , 'clock_out' : '18:00' },
311
+ {'date' : '2023-11-02' , 'clock_in' : '09:05' , 'clock_out' : '17:55' }
312
+ ]
313
+ return jsonify (attendance_records )
314
+
315
+
316
+ # 7. 个人Payroll,加入Advance
317
+ @app .route ('/payroll' , methods = ['GET' ])
318
+ def get_payroll ():
319
+ employee_id = request .args .get ('employee_id' )
320
+ if not employee_id :
321
+ raise BadRequest ('Missing query param: employee_id' )
322
+ # 这里需要从数据库中查询Payroll记录
323
+ payroll_data = {
324
+ 'salary' : 5000 ,
325
+ 'epf' : 550 ,
326
+ 'perkeso' : 50 ,
327
+ 'pcb' : 500 ,
328
+ 'advance' : 200 ,
329
+ 'net_salary' : 4600
330
+ }
331
+ return jsonify (payroll_data )
332
+
333
+
334
+ # 8. Advance 预支工资
335
+ @app .route ('/advance' , methods = ['POST' ])
336
+ def request_advance ():
337
+ data = request .get_json (silent = True ) or {}
338
+ employee_id = data .get ('employee_id' )
339
+ amount = data .get ('amount' )
340
+ if not employee_id :
341
+ raise BadRequest ('Missing field: employee_id' )
342
+ try :
343
+ amount = float (amount )
344
+ except (TypeError , ValueError ):
345
+ raise BadRequest ('Invalid amount' )
346
+ # 这里需要记录预支工资的请求
347
+ return jsonify ({'message' : 'Advance request submitted' })
348
+
349
+
350
+ # 9. 个人资料
351
+ @app .route ('/profile' , methods = ['GET' ])
352
+ def get_profile ():
353
+ employee_id = request .args .get ('employee_id' )
354
+ if not employee_id :
355
+ raise BadRequest ('Missing query param: employee_id' )
356
+ # 这里需要从数据库中查询个人资料
357
+ profile_data = {
358
+ 'name' : 'John Doe' ,
359
+
360
+ 'phone' : '123-456-7890'
361
+ }
362
+ return jsonify (profile_data )
363
+
364
+
365
+ # 9.1 员工管理(Employee Management)
366
+ @app .route ('/employees' , methods = ['GET' ])
367
+ def list_employees ():
368
+ # 返回所有员工列表
369
+ return jsonify (list (employees .values ()))
370
+
371
+
372
+ @app .route ('/employees/<employee_id>' , methods = ['GET' ])
373
+ def get_employee (employee_id ):
374
+ emp = employees .get (employee_id )
375
+ if not emp :
376
+ return jsonify ({'error' : f'Employee { employee_id } not found' }), 404
377
+ return jsonify (emp )
378
+
379
+
380
+ @app .route ('/employees' , methods = ['POST' ])
381
+ def create_employee ():
382
+ data = request .get_json (silent = True ) or {}
383
+ employee_id = data .get ('id' ) or data .get ('employee_id' )
384
+ if not employee_id :
385
+ raise BadRequest ('Missing field: id' )
386
+ if employee_id in employees :
387
+ return jsonify ({'error' : f'Employee { employee_id } already exists' }), 409
388
+
389
+ # 基础字段
390
+ new_emp = {
391
+ 'id' : employee_id ,
392
+ 'name' : data .get ('name' , '' ),
393
+ 'email' : data .get ('email' , '' ),
394
+ 'phone' : data .get ('phone' , '' ),
395
+ 'title' : data .get ('title' , '' ),
396
+ 'department' : data .get ('department' , '' ),
397
+ 'salary' : data .get ('salary' , 0 ),
398
+ 'status' : data .get ('status' , 'active' ),
399
+ }
400
+ employees [employee_id ] = new_emp
401
+ return jsonify (new_emp ), 201
402
+
403
+
404
+ @app .route ('/employees/<employee_id>' , methods = ['PUT' ])
405
+ def update_employee (employee_id ):
406
+ emp = employees .get (employee_id )
407
+ if not emp :
408
+ return jsonify ({'error' : f'Employee { employee_id } not found' }), 404
409
+ data = request .get_json (silent = True ) or {}
410
+ # 更新允许的字段
411
+ for key in ['name' , 'email' , 'phone' , 'title' , 'department' , 'salary' , 'status' ]:
412
+ if key in data :
413
+ emp [key ] = data [key ]
414
+ employees [employee_id ] = emp
415
+ return jsonify (emp )
416
+
417
+
418
+ @app .route ('/employees/<employee_id>' , methods = ['DELETE' ])
419
+ def delete_employee (employee_id ):
420
+ if employee_id not in employees :
421
+ return jsonify ({'error' : f'Employee { employee_id } not found' }), 404
422
+ deleted = employees .pop (employee_id )
423
+ return jsonify ({'message' : 'Deleted' , 'employee' : deleted })
424
+
425
+
426
+ # 10. 聊天功能
427
+ @app .route ('/chat' , methods = ['POST' ])
428
+ def send_message ():
429
+ data = request .get_json (silent = True ) or {}
430
+ sender_id = data .get ('sender_id' )
431
+ receiver_id = data .get ('receiver_id' )
432
+ message = data .get ('message' )
433
+ if not sender_id or not receiver_id or not message :
434
+ raise BadRequest ('Missing sender_id, receiver_id or message' )
435
+ # 这里需要将消息保存到数据库中,并通知接收方
436
+ return jsonify ({'message' : 'Message sent' })
437
+
438
+
439
+ # 11. 语言翻译
440
+ @app .route ('/translate' , methods = ['POST' ])
441
+ def translate_text ():
442
+ data = request .get_json (silent = True ) or {}
443
+ text = data .get ('text' )
444
+ target_language = data .get ('target_language' )
445
+ if not text or not target_language :
446
+ raise BadRequest ('Missing text or target_language' )
447
+ # 这里需要调用翻译API,将文本翻译成目标语言
448
+ # 这里我们只返回一个模拟数据
449
+ translated_text = f'Translated to { target_language } : { text } '
450
+ return jsonify ({'translated_text' : translated_text })
451
+
452
+
453
+ @app .errorhandler (BadRequest )
454
+ def handle_bad_request (err ):
455
+ return jsonify ({'error' : str (err )}), 400
456
+
457
+
458
+ @app .route ('/healthz' )
459
+ def healthz ():
460
+ return jsonify ({'status' : 'ok' })
461
+
462
+
463
+ if __name__ == '__main__' :
464
+ # For local development; in production, use gunicorn with wsgi:app
465
+ app .run (host = '0.0.0.0' , port = 8000 , debug = True )
188
466
189
467
190
468
if __name__ == '__main__' :
0 commit comments