to test
This commit is contained in:
6
.flaskenv
Normal file
6
.flaskenv
Normal file
@ -0,0 +1,6 @@
|
||||
FLASK_APP=inventory_check_lark
|
||||
FLASK_ENV=development
|
||||
SECRET_KEY=asdASS3434dfE5tgfg
|
||||
LARK_APP_ID=cli_a7359bac85b9d01c
|
||||
LARK_APP_SECRECT=vZdiNrSiszH9ODD2qzuI1fHRupOwY5wY
|
||||
LARK_TB_TOKEN=EciWbKOEXa68HIsnh5Ac7vZgnff
|
@ -1,2 +1,8 @@
|
||||
# inventory_check_lark
|
||||
# inventory_check
|
||||
|
||||
|
||||
Flask
|
||||
gunicorn
|
||||
python-dotenv
|
||||
lark-oapi
|
||||
Flask-SQLAlchemy
|
18
inventory_check_lark/__init__.py
Normal file
18
inventory_check_lark/__init__.py
Normal file
@ -0,0 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
:author: luffmims
|
||||
:url: http://yum2.cc
|
||||
:copyright: © 2025 luffmims <luffmims@hotmaill.com>
|
||||
:license: MIT, see LICENSE for more details.
|
||||
"""
|
||||
from flask import Flask
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
application = Flask('inventory_check_lark')
|
||||
application.config.from_pyfile('settings.py')
|
||||
application.jinja_env.trim_blocks = True
|
||||
application.jinja_env.lstrip_blocks = True
|
||||
|
||||
db = SQLAlchemy(application)
|
||||
|
||||
from inventory_check_lark import views, errors, commands
|
19
inventory_check_lark/commands.py
Normal file
19
inventory_check_lark/commands.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
:author: luffmims
|
||||
:url: http://yum2.cc
|
||||
:copyright: © 2025 luffmims <luffmims@hotmaill.com>
|
||||
:license: MIT, see LICENSE for more details.
|
||||
"""
|
||||
import click
|
||||
|
||||
from inventory_check_lark import application
|
||||
|
||||
|
||||
|
||||
@application.cli.command()
|
||||
@click.option('--drop', is_flag=True, help='Create after drop.')
|
||||
def initdb(drop):
|
||||
"""Initialize the database."""
|
||||
click.echo('Initialized database.')
|
||||
|
20
inventory_check_lark/errors.py
Normal file
20
inventory_check_lark/errors.py
Normal file
@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
:author: luffmims
|
||||
:url: http://yum2.cc
|
||||
:copyright: © 2025 luffmims <luffmims@hotmaill.com>
|
||||
:license: MIT, see LICENSE for more details.
|
||||
"""
|
||||
from flask import render_template
|
||||
|
||||
from inventory_check_lark import application
|
||||
|
||||
|
||||
@application.errorhandler(404)
|
||||
def page_not_found(e):
|
||||
return render_template('errors/404.html'), 404
|
||||
|
||||
|
||||
@application.errorhandler(500)
|
||||
def internal_server_error(e):
|
||||
return render_template('errors/500.html'), 500
|
211
inventory_check_lark/models.py
Normal file
211
inventory_check_lark/models.py
Normal file
@ -0,0 +1,211 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
:author: luffmims
|
||||
:url: http://yum2.cc
|
||||
:copyright: © 2025 luffmims <luffmims@hotmaill.com>
|
||||
:license: MIT, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
# from datetime import datetime
|
||||
from inventory_check_lark import application, db
|
||||
import json
|
||||
import time
|
||||
import lark_oapi as lark
|
||||
from lark_oapi.api.auth.v3 import *
|
||||
from lark_oapi.api.bitable.v1 import *
|
||||
|
||||
class Inventory(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
tag = db.Column(db.Text)
|
||||
amount = db.Column(db.Integer)
|
||||
checked = db.Column(db.Boolean, default=False)
|
||||
recordid = db.Column(db.Text)
|
||||
tableid = db.Column(db.Text)
|
||||
# lasttime = db.Column(db.DateTime, default=datetime.now())
|
||||
|
||||
client = lark.Client.builder() \
|
||||
.app_id(application.config['LARK_APP_ID']) \
|
||||
.app_secret(application.config['LARK_APP_SECRECT']) \
|
||||
.log_level(lark.LogLevel.DEBUG) \
|
||||
.build()
|
||||
|
||||
TIMER = time.time()
|
||||
def get_access_token():
|
||||
# 构造请求对象
|
||||
request: InternalAppAccessTokenRequest = InternalAppAccessTokenRequest.builder() \
|
||||
.request_body(InternalAppAccessTokenRequestBody.builder()
|
||||
.app_id(application.config['LARK_APP_ID'])
|
||||
.app_secret(application.config['LARK_APP_SECRECT'])
|
||||
.build()) \
|
||||
.build()
|
||||
|
||||
# 发起请求
|
||||
response: InternalAppAccessTokenResponse = client.auth.v3.app_access_token.internal(request)
|
||||
|
||||
# 处理失败返回
|
||||
# if not response.success():
|
||||
# lark.logger.error(
|
||||
# f"client.auth.v3.app_access_token.internal failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}, resp: \n{json.dumps(json.loads(response.raw.content), indent=4, ensure_ascii=False)}")
|
||||
# return
|
||||
if not response.success():
|
||||
return False
|
||||
return True
|
||||
# # 处理业务结果
|
||||
# res = eval(response.raw.content)
|
||||
# return {"access_token": res["tenant_access_token"], "expire": res["expire"], "code": res["code"]}
|
||||
|
||||
def get_table_record(id, page_token=None):
|
||||
global TIMER
|
||||
if time.time() - TIMER > 7000:
|
||||
get_access_token()
|
||||
TIMER = time.time()
|
||||
# 构造请求对象
|
||||
if page_token:
|
||||
request: SearchAppTableRecordRequest = SearchAppTableRecordRequest.builder() \
|
||||
.app_token(application.config['LARK_TB_TOKEN']) \
|
||||
.table_id(id['table_id']) \
|
||||
.page_token(page_token) \
|
||||
.page_size(50) \
|
||||
.request_body(SearchAppTableRecordRequestBody.builder()
|
||||
.view_id(id['view_id'])
|
||||
.field_names(["规格", "外库数量", "排序", "已盘"])
|
||||
.sort([Sort.builder()
|
||||
.field_name("排序")
|
||||
.desc(False)
|
||||
.build()
|
||||
])
|
||||
.automatic_fields(True)
|
||||
.build()) \
|
||||
.build()
|
||||
else:
|
||||
request: SearchAppTableRecordRequest = SearchAppTableRecordRequest.builder() \
|
||||
.app_token(application.config['LARK_TB_TOKEN']) \
|
||||
.table_id(id['table_id']) \
|
||||
.page_size(50) \
|
||||
.request_body(SearchAppTableRecordRequestBody.builder()
|
||||
.view_id(id['view_id'])
|
||||
.field_names(["规格", "外库数量", "排序", "已盘"])
|
||||
.sort([Sort.builder()
|
||||
.field_name("排序")
|
||||
.desc(False)
|
||||
.build()
|
||||
])
|
||||
.automatic_fields(True)
|
||||
.build()) \
|
||||
.build()
|
||||
|
||||
# 发起请求
|
||||
response: SearchAppTableRecordResponse = client.bitable.v1.app_table_record.search(request)
|
||||
|
||||
# 处理失败返回
|
||||
if not response.success():
|
||||
lark.logger.error(
|
||||
f"client.bitable.v1.app_table_record.search failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}, resp: \n{json.dumps(json.loads(response.raw.content), indent=4, ensure_ascii=False)}")
|
||||
return
|
||||
rep = json.loads(response.raw.content)
|
||||
res = []
|
||||
page_token = None
|
||||
if rep['data']['has_more']:
|
||||
page_token = rep['data']['page_token']
|
||||
for i in rep['data']['items']:
|
||||
if '已盘' in i['fields']:
|
||||
cd = i['fields']['已盘']
|
||||
else:
|
||||
cd = False
|
||||
res.append({
|
||||
"sort": int(i['fields']['排序']),
|
||||
"tag": i['fields']['规格'][0]['text'],
|
||||
"amount": int(i['fields']['外库数量']) if '外库数量' in i['fields'] else 0,
|
||||
"checked": cd,
|
||||
"recordid": i['record_id'],
|
||||
})
|
||||
|
||||
return res, page_token
|
||||
|
||||
def update_record(id, recordid, amount):
|
||||
global TIMER
|
||||
if time.time() - TIMER > 200:
|
||||
get_access_token()
|
||||
TIMER = time.time()
|
||||
# 构造请求对象
|
||||
request: UpdateAppTableRecordRequest = UpdateAppTableRecordRequest.builder() \
|
||||
.app_token(application.config['LARK_TB_TOKEN']) \
|
||||
.table_id(id['table_id']) \
|
||||
.record_id(recordid) \
|
||||
.request_body(AppTableRecord.builder()
|
||||
.fields({"已盘":True,"外库数量":amount})
|
||||
.build()) \
|
||||
.build()
|
||||
|
||||
# 发起请求
|
||||
response: UpdateAppTableRecordResponse = client.bitable.v1.app_table_record.update(request)
|
||||
|
||||
# 处理失败返回
|
||||
# if not response.success():
|
||||
# lark.logger.error(
|
||||
# f"client.bitable.v1.app_table_record.update failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}, resp: \n{json.dumps(json.loads(response.raw.content), indent=4, ensure_ascii=False)}")
|
||||
# return
|
||||
if not response.success():
|
||||
return False
|
||||
# 处理业务结果
|
||||
# lark.logger.info(lark.JSON.marshal(response.raw.content, indent=4))
|
||||
return True
|
||||
|
||||
def init_db():
|
||||
get_access_token()
|
||||
with application.app_context():
|
||||
db.drop_all()
|
||||
db.create_all()
|
||||
|
||||
youxin, page_token= get_table_record(application.config['YOUXIN_ID'])
|
||||
for i in youxin:
|
||||
inv = Inventory()
|
||||
inv.id = i['sort']
|
||||
inv.tag = i['tag']
|
||||
inv.amount = i['amount']
|
||||
inv.checked = i['checked']
|
||||
inv.recordid = i['recordid']
|
||||
inv.tableid = application.config['YOUXIN_ID']
|
||||
db.session.add(inv)
|
||||
while page_token:
|
||||
youxin, page_token = get_table_record(application.config['YOUXIN_ID'], page_token)
|
||||
if not youxin:
|
||||
break
|
||||
for i in youxin:
|
||||
inv = Inventory()
|
||||
inv.id = i['sort']
|
||||
inv.tag = i['tag']
|
||||
inv.amount = i['amount']
|
||||
inv.checked = i['checked']
|
||||
inv.recordid = i['recordid']
|
||||
inv.tableid = application.config['YOUXIN_ID']
|
||||
db.session.add(inv)
|
||||
|
||||
waimo, page_token= get_table_record(application.config['WAIMO_ID'])
|
||||
for i in waimo:
|
||||
inv = Inventory()
|
||||
inv.id = i['sort']
|
||||
inv.tag = i['tag']
|
||||
inv.amount = i['amount']
|
||||
inv.checked = i['checked']
|
||||
inv.recordid = i['recordid']
|
||||
inv.tableid = application.config['WAIMO_ID']
|
||||
db.session.add(inv)
|
||||
while page_token:
|
||||
waimo, page_token = get_table_record(application.config['WAIMO_ID'], page_token)
|
||||
if not waimo:
|
||||
break
|
||||
for i in waimo:
|
||||
inv = Inventory()
|
||||
inv.id = i['sort']
|
||||
inv.tag = i['tag']
|
||||
inv.amount = i['amount']
|
||||
inv.checked = i['checked']
|
||||
inv.recordid = i['recordid']
|
||||
inv.tableid = application.config['WAIMO_ID']
|
||||
db.session.add(inv)
|
||||
|
||||
|
||||
db.session.commit()
|
||||
return True
|
||||
|
45
inventory_check_lark/settings.py
Normal file
45
inventory_check_lark/settings.py
Normal file
@ -0,0 +1,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
:author: luffmims
|
||||
:url: http://yum2.cc
|
||||
:copyright: © 2025 luffmims <luffmims@hotmaill.com>
|
||||
:license: MIT, see LICENSE for more details.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
from inventory_check_lark import application
|
||||
|
||||
# sqlite URI compatible
|
||||
WIN = sys.platform.startswith('win')
|
||||
if WIN:
|
||||
prefix = 'sqlite:///'
|
||||
else:
|
||||
prefix = 'sqlite:////'
|
||||
|
||||
dev_db = prefix + os.path.join(os.path.dirname(application.root_path), 'data.db')
|
||||
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URI', dev_db)
|
||||
SECRET_KEY = os.getenv('SECRET_KEY', 'secret string')
|
||||
|
||||
application.config['LARK_APP_ID'] = os.getenv('LARK_APP_ID', 'lark_app_id')
|
||||
application.config['LARK_APP_SECRECT'] = os.getenv('LARK_APP_SECRECT', 'lark_app_secrect')
|
||||
application.config['LARK_TB_TOKEN'] = os.getenv('LARK_TB_TOKEN', 'lark_app_secrect')
|
||||
|
||||
application.config['WAIMO_ID'] = {
|
||||
'table_id': 'tbluSufkcQm0noBz',
|
||||
'view_id': 'vewLYvBFns',
|
||||
'tag_id': 'fld2xdCqrs',
|
||||
'amount_id': 'fldC9cnnAY',
|
||||
'checked_id': 'fldJkHhQgQ'
|
||||
}
|
||||
|
||||
application.config['YOUXIN_ID'] = {
|
||||
'table_id': 'tbl9NPZQMl5IVHQ2',
|
||||
'view_id': 'vewrOuK32q',
|
||||
'tag_id': 'fldrxqL8uz',
|
||||
'amount_id': 'fldsOIpOBk',
|
||||
'checked_id': 'fldsuS6SuR'
|
||||
}
|
||||
|
39
inventory_check_lark/static/css/style.css
Normal file
39
inventory_check_lark/static/css/style.css
Normal file
@ -0,0 +1,39 @@
|
||||
body {
|
||||
background-color: azure;
|
||||
}
|
||||
main {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
font-size: 18px;
|
||||
}
|
||||
input {
|
||||
width: 4ch;
|
||||
text-align: center;
|
||||
}
|
||||
hr {
|
||||
width: 350px;
|
||||
height: 3px;
|
||||
}
|
||||
.grail{
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
}
|
||||
.handler {
|
||||
width: 350px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: space-between;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
button, input {
|
||||
font-size: 18px;
|
||||
}
|
||||
form {
|
||||
width:350px;
|
||||
}
|
BIN
inventory_check_lark/static/favicon.ico
Normal file
BIN
inventory_check_lark/static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 894 B |
51
inventory_check_lark/static/js/script.js
Normal file
51
inventory_check_lark/static/js/script.js
Normal file
@ -0,0 +1,51 @@
|
||||
function increment() {
|
||||
var amount = document.getElementById("inventory-amount");
|
||||
amount.value = parseInt(amount.value) + 1;
|
||||
}
|
||||
function decrement() {
|
||||
var amount = document.getElementById("inventory-amount");
|
||||
if (amount.value > 0) {
|
||||
amount.value = parseInt(amount.value) - 1;
|
||||
}
|
||||
}
|
||||
function checknext() {
|
||||
var amount = document.getElementById("inventory-amount");
|
||||
// 获取ID为"forid"的元素
|
||||
var idelement = document.getElementById("inventory-id");
|
||||
// 获取该元素的文本内容,并解析为整数
|
||||
var id = parseInt(idelement.innerText, 10); // 第二个参数10表示解析的基数,这里是十进制
|
||||
var tagelement = document.getElementById("inventory-tag");
|
||||
var tag = tagelement.innerText;
|
||||
var msg = document.getElementById("flash-msg");
|
||||
var location = document.getElementById("inventory-location");
|
||||
// var params = new URLSearchParams({
|
||||
// checked: 1,
|
||||
// id: id,
|
||||
// amount: amount.value
|
||||
// });
|
||||
// var url = `/check?${params.toString()}`;
|
||||
fetch('/get_inventory', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({id: id, amount: amount.value})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// console.log('Success:', data);
|
||||
amount.value = data.amount;
|
||||
tagelement.innerText = data.tag;
|
||||
idelement.innerText = data.id;
|
||||
msg.innerText = data.checkedone + " 盘点数 " + data.checkedamount;
|
||||
location.innerText = data.location;
|
||||
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
|
||||
}
|
||||
|
||||
function backtoroot(msg="已完成,返回") {
|
||||
alert(msg);
|
||||
location.href="/";
|
||||
}
|
16
inventory_check_lark/templates/after.html
Normal file
16
inventory_check_lark/templates/after.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>盘库助手</title>
|
||||
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript" src="{{ url_for('static', filename='js/script.js') }}"></script>
|
||||
<script>
|
||||
backtoroot( "{{ msg }}" );
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
28
inventory_check_lark/templates/base.html
Normal file
28
inventory_check_lark/templates/base.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>盘库助手</title>
|
||||
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="grail">
|
||||
<header>
|
||||
<h1>盘点 </h1>
|
||||
</header>
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
<footer>
|
||||
{% block footer %}
|
||||
<small> 2025 © SDHLMH
|
||||
</small>
|
||||
{% endblock %}
|
||||
</footer>
|
||||
</main>
|
||||
|
||||
<script type="text/javascript" src="{{ url_for('static', filename='js/script.js') }}"></script>
|
||||
{% block scripts %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
27
inventory_check_lark/templates/check.html
Normal file
27
inventory_check_lark/templates/check.html
Normal file
@ -0,0 +1,27 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div id="flash-msg">
|
||||
开始盘点>>>
|
||||
</div>
|
||||
<div>
|
||||
<div class="handler">
|
||||
<a href="/"><button type="button">返回</button></a>
|
||||
<div id="inventory-location"></div><div><p id="inventory-id" hidden>{{ inventory.id }}</p></div>
|
||||
</div>
|
||||
<h1 id="inventory-tag">{{ inventory.tag }}</h1>
|
||||
<hr>
|
||||
<div class="handler">
|
||||
<button onclick="decrement()" type="button">减一</button>
|
||||
<input type="number" id="inventory-amount" value="{{ inventory.amount }}" min="0">
|
||||
<button onclick="increment()" type="button">加一</button>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="handler">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<button onclick="checknext()" type="button">确认,下一个</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
11
inventory_check_lark/templates/errors/404.html
Normal file
11
inventory_check_lark/templates/errors/404.html
Normal file
@ -0,0 +1,11 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}404 Error{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<p class="text-center">Page Not Found</p>
|
||||
{% endblock %}
|
||||
|
||||
{% block footer %}
|
||||
<a href="{{ url_for('index') }}">← Go Back</a>
|
||||
{% endblock %}
|
11
inventory_check_lark/templates/errors/500.html
Normal file
11
inventory_check_lark/templates/errors/500.html
Normal file
@ -0,0 +1,11 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}500 Error{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<p class="text-center">Internal Server Error</p>
|
||||
{% endblock %}
|
||||
|
||||
{% block footer %}
|
||||
<a href="{{ url_for('index') }}">← Go Back</a>
|
||||
{% endblock %}
|
16
inventory_check_lark/templates/index.html
Normal file
16
inventory_check_lark/templates/index.html
Normal file
@ -0,0 +1,16 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form method=get action="/init">
|
||||
<input style="width:150px;" type=submit value=初始化>
|
||||
</form>
|
||||
<form method=get action="/check">
|
||||
<input style="width:150px;" type=submit value=继续盘点>
|
||||
</form>
|
||||
<!-- <form method=get action="/download-xlsx">
|
||||
<input style="width:150px;" type=submit value=下载XLSX>
|
||||
</form> -->
|
||||
<div>
|
||||
</div>
|
||||
{% endblock %}
|
17
inventory_check_lark/templates/init.html
Normal file
17
inventory_check_lark/templates/init.html
Normal file
@ -0,0 +1,17 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}上传Excel文件{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>初始化</h1>
|
||||
<div class="handler">
|
||||
<a href="/"><button type="button">返回</button></a>
|
||||
<div></div><div></div>
|
||||
</div>
|
||||
<hr>
|
||||
<form method=post enctype=multipart/form-data action="/import">
|
||||
<div>初始化是从多维表格获取数据,修改多维表格后务必运行,花费约1-5分钟,请耐心等待</div>
|
||||
<div class="handler"><div></div><input style="width:100px;"type=submit value=初始化></div>
|
||||
</form>
|
||||
<div>
|
||||
</div>
|
||||
{% endblock %}
|
76
inventory_check_lark/views.py
Normal file
76
inventory_check_lark/views.py
Normal file
@ -0,0 +1,76 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
:author: luffmims
|
||||
:url: http://yum2.cc
|
||||
:copyright: © 2025 luffmims <luffmims@hotmaill.com>
|
||||
:license: MIT, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from flask import jsonify, request, render_template
|
||||
from inventory_check_lark import application, db
|
||||
from inventory_check_lark.models import init_db, get_access_token, get_table_record, update_record, Inventory
|
||||
from werkzeug.exceptions import BadRequest
|
||||
|
||||
@application.route('/')
|
||||
def index():
|
||||
return render_template('index.html')
|
||||
|
||||
@application.route('/init')
|
||||
def init():
|
||||
return 'ok' if init_db() else 'error'
|
||||
|
||||
@application.route('/check', methods=['GET'])
|
||||
def check():
|
||||
inventory = Inventory.query.filter_by(checked=False).first()
|
||||
if not inventory:
|
||||
return render_template('after.html',msg="未初始化或已盘完")
|
||||
return render_template('check.html',inventory=inventory)
|
||||
|
||||
@application.route('/get_youxin_inventory', methods=['POST'])
|
||||
def update_youxin_inventory():
|
||||
try:
|
||||
# 获取并验证表单数据
|
||||
data = request.get_json()
|
||||
inventory_id = data['id']
|
||||
amount = data['amount']
|
||||
|
||||
if not inventory_id or not amount:
|
||||
raise BadRequest('Missing inventory id or amount')
|
||||
|
||||
# 查询并更新库存对象
|
||||
inventory = Inventory.query.get(inventory_id)
|
||||
if not inventory:
|
||||
raise BadRequest('Inventory not found')
|
||||
checkedone = inventory.tag
|
||||
inventory.amount = amount
|
||||
inventory.checked = True
|
||||
update_record(inventory.tableid, inventory.recordid, amount)
|
||||
|
||||
# 提交更改
|
||||
db.session.commit()
|
||||
|
||||
# 显示成功消息
|
||||
# flash(f'{inventory.tag} checked and updated')
|
||||
id = inventory_id + 1
|
||||
inventory = Inventory.query.get(id)
|
||||
if not inventory:
|
||||
raise BadRequest('Inventory not found')
|
||||
# 返回更新后的库存信息
|
||||
return jsonify({
|
||||
'id': inventory.id,
|
||||
'tag': inventory.tag,
|
||||
'amount': inventory.amount,
|
||||
'checkedone': checkedone,
|
||||
'checkedamount': amount
|
||||
})
|
||||
|
||||
except BadRequest as e:
|
||||
# 处理错误情况
|
||||
# flash(str(e))
|
||||
return jsonify({'error': str(e)}), 400
|
||||
|
||||
except Exception as e:
|
||||
# 处理其他可能的错误
|
||||
db.session.rollback()
|
||||
# flash('An error occurred while updating the inventory')
|
||||
return jsonify({'error': 'Internal server error'}), 500
|
Reference in New Issue
Block a user