Compare commits

...

23 Commits

Author SHA1 Message Date
39b0cb2418 Revert "fix: update order cancellation response check to use 'result' key"
This reverts commit 241785ab91.
2025-09-01 07:08:13 +03:00
241785ab91 fix: update order cancellation response check to use 'result' key 2025-09-01 07:07:48 +03:00
ba7000f3d9 feat: implement order cancellation for assemblies and handle error responses 2025-09-01 07:07:28 +03:00
489d470c7b feat: add response for users with existing active assemblies 2025-08-15 04:22:03 +03:00
485e6eacd2 feat: add application name filter to version query 2025-06-09 12:06:43 +03:00
4ebb7ce0fc feat: implement close_assembly_by_id function and confirm_current_assembly endpoint 2025-05-29 15:38:40 +03:00
9c904ae138 feat: add support for multiple label formats in get_label function 2025-05-26 22:48:51 +03:00
6ca3a9372a feat: add support for multiple label formats in get_label function 2025-05-26 22:43:52 +03:00
39087fc223 refactor: remove confirmed state filter from assembly queries 2025-05-24 00:05:23 +03:00
47ac3908f6 feat: ozon supplies 2025-04-02 03:44:34 +03:00
d6dc39ef61 crpt 2025-01-13 05:10:55 +03:00
4d7e5ded4d crpt 2024-10-12 03:55:00 +03:00
7512b3347e feat: assembly additional statistics 2024-03-05 07:16:24 +03:00
7e853c48e7 feat: balance and reward 2024-02-24 15:38:48 +03:00
c8a234e27b feat: get users sipro 2024-02-22 07:51:17 +03:00
b302feec1d Merge remote-tracking branch 'origin/master' 2023-12-20 01:06:26 +03:00
6dea56e3ee feat: cancel assembly by id 2023-12-20 01:04:20 +03:00
dc8d9d242b assembly statistics 2023-12-11 01:53:30 +04:00
34be5a198d assembly statistics 2023-12-11 01:50:49 +04:00
c508a3ee33 feat: user create and delete 2023-11-26 06:12:26 +03:00
f0b1c030f3 feat: admin panel 2023-11-25 09:01:55 +03:00
43cd50d5cd feat: admin panel 2023-11-25 08:56:44 +03:00
347eb9730c feat: admin panel 2023-11-25 08:46:02 +03:00
34 changed files with 527 additions and 88 deletions

1
app.py
View File

@@ -32,6 +32,7 @@ blueprints = [
(routes.application_blueprint, '/application'),
(routes.sipro_blueprint, '/sipro'),
(routes.admin_blueprint, '/admin'),
(routes.balance_blueprint, '/balance'),
]
for blueprint, url_prefix in blueprints:

View File

@@ -9,3 +9,9 @@ def to_nested_dict(row):
current_level = current_level[part]
current_level[keys[-1]] = value
return result
def compile_query_to_plain_sql(query) -> str:
return query.statement.compile(compile_kwargs={
'literal_binds': True
})

View File

@@ -1 +1,4 @@
from database.models import *
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
from .models import *

View File

@@ -8,3 +8,9 @@ class AssemblyState(IntEnum):
ALL_PRODUCTS_ASSEMBLED = 2,
CONFIRMED = 3,
ENDED = 4
@unique
class BalanceTransactionType(IntEnum):
TOP_UP = 0
WITHDRAW = 1

View File

@@ -0,0 +1,2 @@
from .basic import *
from .balance import *

View File

@@ -0,0 +1,40 @@
from sqlalchemy import Connection, func
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapper
import database
from database import db
class BalanceTransaction(db.Model):
__tablename__ = 'balance_transactions'
id = db.Column(db.Integer, primary_key=True, comment='ID транзакции')
type = db.Column(db.Integer, nullable=False, comment='Тип транзакции')
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
user = db.relationship('User', backref='transactions')
amount = db.Column(db.Double, nullable=False, comment='Сумма транзакции')
description = db.Column(db.Text, nullable=False, comment='Описание')
json_data = db.Column(JSONB, comment='JSON данные')
created_at = db.Column(db.DateTime, nullable=False, comment='Дата и время создания транзакции')
def recalculate_user_balance(user_id: int):
user_balance = (database.BalanceTransaction.query.filter_by(user_id=user_id)
.group_by(database.BalanceTransaction.user_id)
.with_entities(func.sum(database.BalanceTransaction.amount))
.scalar()) or 0
(db.session.query(database.User)
.filter_by(id=user_id)
.update({'balance': user_balance}, synchronize_session='fetch'))
@db.event.listens_for(BalanceTransaction, 'after_insert')
def after_balance_transaction_insert(mapper: Mapper, connection: Connection, target: BalanceTransaction):
recalculate_user_balance(target.user_id)
@db.event.listens_for(BalanceTransaction, 'after_delete')
def after_balance_transaction_delete(mapper: Mapper, connection: Connection, target: BalanceTransaction):
recalculate_user_balance(target.user_id)

View File

@@ -1,6 +1,4 @@
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
from database import db
class User(db.Model):
@@ -14,6 +12,7 @@ class User(db.Model):
is_admin = db.Column(db.Boolean, nullable=False, default=False, server_default='0', comment='Админ ли юзверь')
city_id = db.Column(db.Integer, nullable=False, default='1', server_default='1', comment='ID страны')
balance = db.Column(db.Double, nullable=False, default=0, server_default='0', comment='Баланс пользователя')
class Assembly(db.Model):

View File

View File

@@ -0,0 +1,4 @@
from .requests import (
get_balance_transactions,
get_balance_info
)

View File

@@ -0,0 +1,29 @@
import database
from ..schemas.requests import *
from ..schemas.responses import *
from ..schemas.entities import *
def get_balance_transactions(data: dict):
items_per_page = 5
request = GetBalanceTransactionsRequest.model_validate(data)
page = max([request.page - 1, 0])
query = (database.BalanceTransaction.query
.filter(database.BalanceTransaction.user_id == request.user_id)
.order_by(database.BalanceTransaction.created_at.desc())
.offset(items_per_page * page)
.limit(items_per_page)
.all())
balance_transactions = [BalanceTransaction.model_validate(balance_transaction) for balance_transaction in query]
response = GetBalanceTransactionsResponse(balance_transactions=balance_transactions)
return response.to_dict()
def get_balance_info(data: dict):
request = GetBalanceInfoRequest.model_validate(data)
balance = (database.User.query
.filter_by(id=request.user_id)
.with_entities(database.User.balance)
.scalar())
response = GetBalanceInfoResponse(balance=balance)
return response.to_dict()

View File

View File

@@ -0,0 +1,13 @@
from datetime import datetime
from schemas.base import CommonModel
class BalanceTransaction(CommonModel):
id: int
type: int
user_id: int
amount: float
description: str
json_data: dict | None = None
created_at: datetime

View File

@@ -0,0 +1,10 @@
from schemas.base import CommonModel
class GetBalanceTransactionsRequest(CommonModel):
page: int
user_id: int
class GetBalanceInfoRequest(CommonModel):
user_id: int

View File

@@ -0,0 +1,12 @@
from typing import List
from schemas.base import CommonModel
from .entities import BalanceTransaction
class GetBalanceTransactionsResponse(CommonModel):
balance_transactions: List[BalanceTransaction]
class GetBalanceInfoResponse(CommonModel):
balance: float

View File

@@ -14,4 +14,5 @@ mariadb
# Other stuff
requests
python-dotenv
python-dotenv
pydantic

View File

@@ -1,9 +1,10 @@
from routes.auth import auth_blueprint
from routes.orders import orders_blueprint
from routes.barcode import barcode_blueprint
from routes.printing import printing_blueprint
from routes.assembly import assembly_blueprint
from routes.general import general_blueprint
from routes.application import application_blueprint
from routes.sipro import sipro_blueprint
from routes.admin import admin_blueprint
from .auth import auth_blueprint
from .orders import orders_blueprint
from .barcode import barcode_blueprint
from .printing import printing_blueprint
from .assembly import assembly_blueprint
from .general import general_blueprint
from .application import application_blueprint
from .sipro import sipro_blueprint
from .admin import admin_blueprint
from .balance import balance_blueprint

View File

@@ -56,16 +56,41 @@ def get_user(user_id):
@admin_blueprint.put('/user/<int:user_id>')
def put_user(user_id):
params: dict = request.json
password = params.get('password').strip()
password = params.get('password')
if password:
password = password.strip()
if password:
params['password_hash'] = generate_password_hash(password)
del params['password']
if 'password' in params:
del params['password']
database.db.session.bulk_update_mappings(database.User, [params])
database.db.session.commit()
user = database.db.session.get(database.User, user_id)
return format_user(user)
@admin_blueprint.post('/user')
def create_user():
args: dict = request.json
args['password_hash'] = generate_password_hash(args['password'])
del args['password']
new_user = database.User(**args)
database.db.session.add(new_user)
database.db.session.flush()
database.db.session.commit()
return format_user(new_user)
@admin_blueprint.delete('/user/<int:user_id>')
def delete_user(user_id):
user = database.db.session.get(database.User, user_id)
if user:
database.db.session.delete(user)
database.db.session.commit()
return '', 200
@admin_blueprint.get('/city')
def get_cities():
filters = request.args.get('filter')

View File

@@ -55,7 +55,8 @@ def upload(application_name: str):
return {"error": "Invalid form data. There is no file or version field"}, 400
version = version.strip()
application = (database.Application.query.
filter_by(version=version).
filter_by(version=version,
name=application_name).
with_entities(database.Application.id).first())
if application:
return {"error": f"Specified version ({version}) already uploaded"}, 400

View File

@@ -2,11 +2,13 @@ import datetime
from flask import Blueprint, request, jsonify
from flask_jwt_extended import get_jwt_identity
from sqlalchemy.orm import joinedload
import database
from database.enums import AssemblyState
from routes.utils import jwt_protect_blueprint
import sipro.api.orders
import utils.balance
assembly_blueprint = jwt_protect_blueprint(Blueprint('assembly', __name__))
@@ -17,15 +19,33 @@ def create_assembly():
data: dict = request.json
order_id: int = data.get('orderId')
user_id = get_jwt_identity()
existing_assembly = database.Assembly.query.filter_by(order_id=order_id).first()
existing_assembly = (database.Assembly.query.
options(joinedload(database.Assembly.user)).
filter_by(order_id=order_id).
first())
if existing_assembly:
response = {
'ok': False,
'message': 'Сборка этого товара уже была запущена',
'assemblyId': existing_assembly.id,
'statusCode': 'ASSEMBLY_ALREADY_EXISTS'
'statusCode': 'ASSEMBLY_ALREADY_EXISTS',
'userName': existing_assembly.user.login
}
return jsonify(response)
need_crpt_for_order_response = sipro.api.orders.need_crpt_by_order_id(order_id)
need_crpt_value = need_crpt_for_order_response.get('needCrpt')
if need_crpt_value:
valid_app = request.headers.get('CrptAvailable')
if not valid_app:
response = {
'ok': False,
'message': 'Для сборки этого заказа необходимо приложение с поддержкой Честного Знака',
'assemblyId': -1,
'statusCode': 'USER_ALREADY_HAS_ACTIVE_ASSEMBLY',
}
return jsonify(response)
active_assembly = database.Assembly.query.filter(database.Assembly.user_id == user_id,
database.Assembly.is_active == True).first()
if active_assembly:
@@ -36,6 +56,22 @@ def create_assembly():
'statusCode': 'USER_ALREADY_HAS_ACTIVE_ASSEMBLY'
}
return jsonify(response)
assembled_assembly = (
database.Assembly.query
.filter(
database.Assembly.order_id == order_id,
database.Assembly.ended_at != None
)
.first()
)
if assembled_assembly:
response = {
'ok': False,
'message': 'Вы уже собирали этот товар',
'assemblyId': assembled_assembly.id,
'statusCode': 'USER_ALREADY_HAS_ACTIVE_ASSEMBLY',
}
return jsonify(response)
assembly = database.Assembly(user_id=user_id,
order_id=order_id,
state=AssemblyState.NOT_STARTED,
@@ -60,10 +96,9 @@ def create_assembly():
return jsonify(response)
@assembly_blueprint.post('/close')
def close_assembly():
args = request.json
assembly_id = args.get('assemblyId')
def close_assembly_by_id(
assembly_id: int,
):
if not assembly_id or (not isinstance(assembly_id, int)):
response = {
'ok': False,
@@ -81,7 +116,25 @@ def close_assembly():
assembly.ended_at = datetime.datetime.now()
database.db.session.commit()
order_id = assembly.order_id
return sipro.api.orders.close_order(order_id)
sipro_response = sipro.api.orders.close_order(order_id)
reward = sipro_response.get('reward')
ok = sipro_response.get('ok')
if ok:
utils.balance.add_top_up(user_id=assembly.user_id,
amount=reward,
description=f'Начисление за сборку заказа {order_id}',
json_data={'order_id': order_id},
commit=True)
return sipro_response
@assembly_blueprint.post('/close')
def close_assembly():
args = request.json
assembly_id = args.get('assemblyId')
sipro_response = close_assembly_by_id(int(assembly_id))
return sipro_response
@assembly_blueprint.post('/cancel')
@@ -96,6 +149,14 @@ def cancel_assembly():
'message': 'У вас нет активных сборок'
}
return jsonify(response)
order_id = assembly.order_id
sipro_response = sipro.api.orders.cancel_order_assembly(order_id)
if not sipro_response.get('ok'):
response = {
'ok': False,
'message': f'Ошибка: {sipro_response.get("message")}'
}
return jsonify(response)
database.db.session.delete(assembly)
database.db.session.commit()
response = {
@@ -111,6 +172,32 @@ def cancel_assembly():
return jsonify(response)
@assembly_blueprint.post('/cancelById')
def cancel_assembly_by_id():
try:
assembly_id = request.json.get('assemblyId')
assembly = database.db.session.get(database.Assembly, assembly_id)
if not assembly:
response = {
'ok': False,
'message': f'Сборка {assembly_id} не найдена'
}
return jsonify(response)
database.db.session.delete(assembly)
database.db.session.commit()
response = {
'ok': True,
'message': f'Сборка {assembly_id} успешно отменена!'
}
return jsonify(response)
except Exception as e:
response = {
'ok': False,
'message': f'Неудалось отменить сборку, ошибка: {e}'
}
return jsonify(response)
@assembly_blueprint.get('/hasActive')
def user_has_active_assembly():
user_id = get_jwt_identity()
@@ -135,6 +222,26 @@ def get_active_assembly():
return jsonify(response)
@assembly_blueprint.post('/confirmCurrent')
def confirm_current_assembly():
# confirm current assembly for user
user_id = get_jwt_identity()
assembly = database.Assembly.query.filter(database.Assembly.user_id == user_id,
database.Assembly.is_active == True).first()
if not assembly:
response = {
'ok': False,
'message': 'У вас нет активных сборок'
}
return jsonify(response)
close_assembly_by_id(assembly.id)
response = {
'ok': True,
'message': 'Сборка успешно завершена!',
}
return response
@assembly_blueprint.post('/confirm')
def confirm_assembly():
user_id = get_jwt_identity()
@@ -179,3 +286,16 @@ def update_assembly_state():
except Exception as e:
print('Error while updating')
return jsonify(ok=False)
@assembly_blueprint.get('/needCrpt')
def need_crpt():
order_product_id = request.args.get('orderProductId')
return sipro.api.orders.need_crpt(order_product_id)
@assembly_blueprint.post('/attachCrpt')
def attach_crpt():
order_product_id = request.json.get('orderProductId')
crpt = request.json.get('crpt')
return sipro.api.orders.attach_crpt(order_product_id, crpt)

23
routes/balance.py Normal file
View File

@@ -0,0 +1,23 @@
from flask import Blueprint, request
from flask_jwt_extended import get_jwt_identity
from routes.utils import jwt_protect_blueprint
import queries.balance.api as api
balance_blueprint = jwt_protect_blueprint(Blueprint('balance', __name__))
@balance_blueprint.get('/transactions')
def get_transactions():
data = dict(request.args)
if 'user_id' not in data:
data['user_id'] = get_jwt_identity()
response = api.get_balance_transactions(dict(data))
return response
@balance_blueprint.get('/info')
def get_balance_info():
data = {'user_id': get_jwt_identity()}
response = api.get_balance_info(data)
return response

View File

@@ -1,4 +1,4 @@
from flask import Blueprint, jsonify, request
from flask import Blueprint
from routes.utils import jwt_protect_blueprint
import sipro.api.general

View File

@@ -33,10 +33,10 @@ def get_orders():
@orders_blueprint.get('/getByProductId')
def get_orders_by_supplier_product_id():
#user_id = get_jwt_identity()
#city_id = database.db.session.get(database.User, user_id).city_id
user_id = get_jwt_identity()
city_id = database.db.session.get(database.User, user_id).city_id
params = dict(request.args)
#params['city'] = city_id
params['city'] = city_id
return sipro.api.orders.get_orders_from_barcode(params=params)

View File

@@ -1,4 +1,6 @@
from flask import Blueprint, request, send_file
import json
from flask import Blueprint, request, send_file, jsonify
from routes.utils import jwt_protect_blueprint
import sipro.api.printing
@@ -9,9 +11,14 @@ printing_blueprint = jwt_protect_blueprint(Blueprint('printing', __name__))
def get_label():
args = request.args
order_id = args.get('orderId')
data = sipro.api.printing.get_label(order_id)
label_format = args.get('format', 'pdf')
data = sipro.api.printing.get_label(order_id, label_format=label_format)
data.seek(0)
return send_file(data,
as_attachment=True,
download_name='label.pdf',
mimetype='application/pdf')
if label_format == 'pdf':
return send_file(data,
as_attachment=True,
download_name='label.pdf',
mimetype='application/pdf')
data= json.loads(str(data.read(), 'ascii'))
return jsonify(data)

View File

@@ -1,10 +1,11 @@
import datetime
from enum import StrEnum
from flask import Blueprint, request
from sqlalchemy import func
from flask import Blueprint, request, jsonify
from sqlalchemy import func, cast, String, Numeric, Float
import auxiliary
import database
import database.enums
sipro_blueprint = Blueprint('sipro', __name__)
@@ -51,3 +52,118 @@ def assembly_info():
result = query.all()
json_result = [auxiliary.to_nested_dict(row) for row in result]
return json_result
@sipro_blueprint.post('/tableAssemblyStats')
def table_assembly_stats():
filters = request.json
date_from = filters.get('from')
date_to = filters.get('to')
dated_query = (
database.Assembly.query
.join(database.User)
.filter(
database.User.is_admin == False
)
.group_by(database.User.login, database.Assembly.user_id)
.with_entities(
database.User.login.label('user_login'),
func.count(database.Assembly.user_id).label('assembled'),
func.string_agg(func.cast(database.Assembly.order_id, database.db.String), ',').label('order_ids')
)
)
if len(date_from) > 0 and len(date_to) > 0:
dated_query = dated_query.filter(
database.Assembly.ended_at >= date_from,
database.Assembly.ended_at <= date_to
)
json_result = []
for row in dated_query.all():
json_result.append({
'user_login': row.user_login,
'assembled': row.assembled,
'order_ids': row.order_ids
})
return jsonify(json_result)
@sipro_blueprint.get('/dailyAssemblyData')
def daily_assembly_stats():
query = (
database.Assembly.query
.join(database.User)
.filter(
database.Assembly.ended_at >= func.current_date()
)
.group_by(database.User.login, database.Assembly.user_id)
.with_entities(
database.User.login.label('user_login'),
func.count(database.Assembly.user_id).label('assembled'),
func.string_agg(func.cast(database.Assembly.order_id, database.db.String), ',').label('order_ids')
)
)
json_result = []
for row in query.all():
json_result.append({
'user_login': row.user_login,
'assembled': row.assembled,
'order_ids': row.order_ids
})
return json_result
@sipro_blueprint.get('/users')
def get_users():
query = (database.User.query.
with_entities(database.User.id,
database.User.login)
.all())
response = [{'id': user.id, 'login': user.login} for user in query]
return jsonify(response)
@sipro_blueprint.get('/statistics')
def get_users_statistics():
data: dict = request.args
user_id = int(data['userId'])
date_from = datetime.datetime.fromisoformat(data['dateFrom'])
date_to = datetime.datetime.fromisoformat(data['dateTo']) + datetime.timedelta(hours=24, minutes=59, seconds=59)
query = (database.BalanceTransaction.query
.filter(database.BalanceTransaction.user_id == user_id,
database.BalanceTransaction.created_at.between(date_from, date_to))
.order_by(func.date_trunc('day', database.BalanceTransaction.created_at))
.group_by(func.date_trunc('day', database.BalanceTransaction.created_at))
.with_entities(func.date_trunc('day', database.BalanceTransaction.created_at).label('date'),
func.cast(func.round(func.cast(func.sum(database.BalanceTransaction.amount), Numeric), 2),
Float).label(
'value'),
func.string_agg(cast(database.BalanceTransaction.json_data['order_id'], String), ',').label(
'order_ids'))
.all())
result = [{'date': row.date.isoformat(), 'value': row.value, 'order_ids': row.order_ids} for row in query]
return jsonify(result)
@sipro_blueprint.get('/get-orders-by-date')
def get_orders_by_date():
data: dict = request.args
date = datetime.date.fromisoformat(data['date'])
query = (
database.Assembly.query
.filter(
func.date_trunc('day', database.Assembly.ended_at) == func.date_trunc('day', date),
)
.with_entities(
func.string_agg(func.cast(database.Assembly.order_id, database.db.String), ',').label('order_ids')
)
.scalar()
)
if not query:
return jsonify({'order_ids': []})
return jsonify({'order_ids': list(map(int, query.split(',')))})

View File

@@ -1,13 +0,0 @@
from enum import unique, IntEnum
@unique
class CodeType(IntEnum):
BARCODE = 0
QRCODE = 1
INVALID = 2
@unique
class SearchType(IntEnum):
PRODUCT = 0

View File

@@ -1,11 +0,0 @@
from scanner.enums import CodeType
from scanner.utils import guess_code_type
class ScannerSearch:
def __init__(self, string_value: str):
self.string_value = string_value
self._code_type = guess_code_type(self.string_value)
def get_code_type(self) -> CodeType:
return self._code_type

View File

@@ -1,9 +0,0 @@
from scanner.enums import CodeType
def guess_code_type(string_value: str) -> CodeType:
if string_value.isdigit():
return CodeType.BARCODE
if string_value:
return CodeType.QRCODE
return CodeType.INVALID

0
schemas/__init__.py Normal file
View File

20
schemas/base.py Normal file
View File

@@ -0,0 +1,20 @@
from pydantic import BaseModel
from pydantic.alias_generators import to_camel
class CommonConfig:
alias_generator = to_camel
populate_by_name = True
from_attributes = True
class CommonModel(BaseModel):
class Config(CommonConfig):
pass
@classmethod
def json_serialize(cls, obj):
return cls.model_validate(obj).model_dump(by_alias=True)
def to_dict(self, by_alias=True):
return self.model_dump(by_alias=by_alias)

View File

@@ -40,3 +40,29 @@ def get_orders_from_barcode(params: dict):
method = f'{router}/getByProductId'
response = client.method('GET', method, params=params)
return response
def need_crpt(order_product_id):
method = f'{router}/needCrpt?orderProductId={order_product_id}'
response = client.method('GET', method)
return response
def attach_crpt(order_product_id, crpt):
method = f'{router}/attachCrpt'
data = {'orderProductId': order_product_id, 'crpt': crpt}
response = client.method('POST', method, data=data)
return response
def need_crpt_by_order_id(order_id):
method = f'{router}/needCrptByOrder?orderId={order_id}'
response = client.method('GET', method)
return response
def cancel_order_assembly(order_id):
method = f'{router}/cancelOrderAssembly'
data = {'orderId': order_id}
response = client.method('POST', method, data=data)
return response

View File

@@ -9,8 +9,8 @@ client = get_client()
router = '/printing'
def get_label(order_product_id: str) -> BytesIO:
method = f'{router}/getLabel?orderId={order_product_id}'
def get_label(order_product_id: str, label_format:str='pdf') -> BytesIO:
method = f'{router}/getLabel?orderId={order_product_id}&format={label_format}'
response: Response = client.method('GET', method, raw=True)
data = BytesIO(response.content)
return data

23
utils/balance.py Normal file
View File

@@ -0,0 +1,23 @@
import datetime
import database
import database.enums
def add_top_up(user_id: int,
amount: float,
description: str,
json_data: dict,
commit=False):
transaction = database.BalanceTransaction(
user_id=user_id,
type=database.enums.BalanceTransactionType.TOP_UP,
amount=amount,
description=description,
json_data=json_data,
created_at=datetime.datetime.now()
)
database.db.session.add(transaction)
if commit:
database.db.session.commit()

View File

@@ -1,16 +0,0 @@
import database
from database.mariadb import MariadbConnector
class BarcodesSynchronizer:
def __init__(self):
self.mariadb_connector = MariadbConnector()
def synchronize(self):
existing_barcodes = database.Barcode.query.all()
denco_articles = list(set([barcode.denco_article for barcode in existing_barcodes]))
query_string = 'SELECT product, barcode FROM modx_0_connections WHERE barcode != "" LIMIT 100'
for denco_article, barcodes_string in self.mariadb_connector.select(query_string):
barcodes = barcodes_string.split(',')
print(denco_article, barcodes)