kassa added
This commit is contained in:
47
kassa/atol.py
Normal file
47
kassa/atol.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class Atol:
|
||||||
|
def __init__(self, token):
|
||||||
|
self.token = token
|
||||||
|
# Вызовы функций
|
||||||
|
self.load_info()
|
||||||
|
# self.get_token()
|
||||||
|
|
||||||
|
def load_info(self):
|
||||||
|
self.url = "https://online.atol.ru/possystem/v4/"
|
||||||
|
self.group_id = 'jkhsakha-ru_3289'
|
||||||
|
|
||||||
|
def get_headers(self):
|
||||||
|
headers_dict = {
|
||||||
|
"Content-type": "application/json",
|
||||||
|
"charset": "utf-8",
|
||||||
|
"Token": self.token, }
|
||||||
|
return headers_dict
|
||||||
|
|
||||||
|
def get_request(self, method, url, data):
|
||||||
|
if method == "post":
|
||||||
|
r = requests.post(self.url+url, data=json.dumps(data),
|
||||||
|
headers=self.get_headers())
|
||||||
|
else:
|
||||||
|
r = requests.get(self.url+url, headers=self.get_headers())
|
||||||
|
r.encoding = "utf-8"
|
||||||
|
return json.loads(r.text)
|
||||||
|
|
||||||
|
def get_token(self, login, password):
|
||||||
|
self.login = login
|
||||||
|
self.password = password
|
||||||
|
d = {"login": self.login, "pass": self.password}
|
||||||
|
self.token, _, self.timestamp = self.get_request(
|
||||||
|
"post", "getToken", d).values()
|
||||||
|
return self.token
|
||||||
|
|
||||||
|
def set_sell(self, reciept, is_refund):
|
||||||
|
func = '/sell' if is_refund == 0 else '/sell_refund'
|
||||||
|
s = self.get_request('post', self.group_id+func, reciept)
|
||||||
|
return s
|
||||||
|
|
||||||
|
def get_reciepts(self, uuid):
|
||||||
|
r = self.get_request('get', self.group_id+'/' + 'report/'+uuid, None)
|
||||||
|
return r
|
0
kassa/cruds/correction.py
Normal file
0
kassa/cruds/correction.py
Normal file
53
kassa/cruds/doc.py
Normal file
53
kassa/cruds/doc.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
from ast import Dict
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
import schemas
|
||||||
|
import models
|
||||||
|
|
||||||
|
|
||||||
|
def create_doc(db: Session, doc: schemas.Doc, external_id: str = None):
|
||||||
|
d = doc.dict()
|
||||||
|
external_id = external_id.lower()
|
||||||
|
doc_query = db.query(models.Doc).filter(
|
||||||
|
models.Doc.external_id == external_id)
|
||||||
|
error = d.pop('error', None)
|
||||||
|
payload = d.pop('payload', None)
|
||||||
|
warnings = d.pop('warnings', None)
|
||||||
|
if error:
|
||||||
|
create_error(db, error, external_id)
|
||||||
|
if payload:
|
||||||
|
create_payload(db, payload, external_id)
|
||||||
|
if doc_query.first():
|
||||||
|
doc_query.update(values=d)
|
||||||
|
else:
|
||||||
|
doc_query = models.Doc(**d)
|
||||||
|
db.add(doc_query)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def create_error(db: Session, error: schemas.Error, external_id: str = None):
|
||||||
|
err = error
|
||||||
|
err['external_id'] = external_id
|
||||||
|
err_query = db.query(models.Error).filter(
|
||||||
|
models.Error.external_id == external_id)
|
||||||
|
if err_query.first():
|
||||||
|
|
||||||
|
err_query.update(values=err)
|
||||||
|
else:
|
||||||
|
err_query = models.Error(**err, synchronize_session=False)
|
||||||
|
db.add(err_query)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def create_payload(db: Session, payload: schemas.Payload, external_id: str = None):
|
||||||
|
pay = payload
|
||||||
|
|
||||||
|
payload_query = db.query(models.Payload).filter(
|
||||||
|
models.Payload.external_id == external_id)
|
||||||
|
if payload_query.first():
|
||||||
|
payload_query.update(pay, synchronize_session=False)
|
||||||
|
|
||||||
|
else:
|
||||||
|
pay['external_id'] = external_id
|
||||||
|
model = models.Payload(**pay)
|
||||||
|
db.add(model)
|
||||||
|
db.commit()
|
0
kassa/cruds/sell.py
Normal file
0
kassa/cruds/sell.py
Normal file
17
kassa/databases.py
Normal file
17
kassa/databases.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
from sqlalchemy import create_engine
|
||||||
|
|
||||||
|
Base = declarative_base()
|
||||||
|
SQL_ALCHEMY_DATABASE_URL_MSSQL = f'mssql+pyodbc://sa:159357@Sanctuary/Atol?driver=SQL+Server'
|
||||||
|
engine = create_engine(
|
||||||
|
SQL_ALCHEMY_DATABASE_URL_MSSQL, connect_args={'check_same_thread': False})
|
||||||
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||||
|
|
||||||
|
|
||||||
|
def get_db():
|
||||||
|
db = SessionLocal()
|
||||||
|
try:
|
||||||
|
yield db
|
||||||
|
finally:
|
||||||
|
db.close()
|
15
kassa/kassa.py
Normal file
15
kassa/kassa.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from fastapi import APIRouter, Depends
|
||||||
|
import databases
|
||||||
|
import cruds.doc as doc
|
||||||
|
import schemas
|
||||||
|
import models
|
||||||
|
|
||||||
|
models.Base.metadata.create_all(databases.engine)
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
get_db = databases.get_db
|
||||||
|
|
||||||
|
|
||||||
|
@router.post('/{external_id}')
|
||||||
|
def insert_doc(request: schemas.Doc, external_id: str, db=Depends(get_db)):
|
||||||
|
return doc.create_doc(db, request, external_id)
|
80
kassa/models.py
Normal file
80
kassa/models.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
from sqlalchemy.sql.schema import ForeignKey
|
||||||
|
from sqlalchemy import Column, Integer, String, Numeric, DateTime, Boolean
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
|
from databases import Base
|
||||||
|
|
||||||
|
|
||||||
|
class Payment(Base):
|
||||||
|
__tablename__ = 'payments'
|
||||||
|
|
||||||
|
id = Column('id', Integer, primary_key=True, autoincrement=True)
|
||||||
|
external_id = Column('external_id', String(length=128))
|
||||||
|
type = Column('type', Integer)
|
||||||
|
sum = Column('sum', Numeric(12, 2))
|
||||||
|
|
||||||
|
|
||||||
|
class CorrectionInfoTable(Base):
|
||||||
|
__tablename__ = 'correction_info'
|
||||||
|
|
||||||
|
external_id = Column('external_id', String(length=128), primary_key=True)
|
||||||
|
type = Column('type', String(length=10))
|
||||||
|
base_date = Column('base_date', String(length=128))
|
||||||
|
base_number = Column('base_number', String(length=128))
|
||||||
|
|
||||||
|
|
||||||
|
class Error(Base):
|
||||||
|
__tablename__ = 'errors'
|
||||||
|
|
||||||
|
external_id = Column('external_id', String(length=128), primary_key=True)
|
||||||
|
error_id = Column('error_id', String(length=128))
|
||||||
|
code = Column('code', Integer)
|
||||||
|
text = Column('text', String(length=250))
|
||||||
|
type = Column('type', String(length=10))
|
||||||
|
|
||||||
|
|
||||||
|
class Doc(Base):
|
||||||
|
__tablename__ = 'docs'
|
||||||
|
uuid = Column('uuid', String(length=128), primary_key=True)
|
||||||
|
timestamp = Column('timestamp', String(length=128))
|
||||||
|
group_code = Column('group_code', String(length=128))
|
||||||
|
daemon_code = Column('daemon_code', String(length=128))
|
||||||
|
device_code = Column('device_code', String(length=128))
|
||||||
|
external_id = Column('external_id', String(length=128))
|
||||||
|
callback_url = Column('callback_url', String(length=128))
|
||||||
|
status = Column('status', String(length=128))
|
||||||
|
|
||||||
|
|
||||||
|
class Atol(Base):
|
||||||
|
__tablename__ = 'atol_receipts'
|
||||||
|
uuid = Column('uuid', String(length=128), primary_key=True)
|
||||||
|
timestamp = Column('timestamp', String(length=128))
|
||||||
|
external_id = Column('external_id', String(length=128))
|
||||||
|
status = Column('status', String(length=128))
|
||||||
|
|
||||||
|
|
||||||
|
class Payload(Base):
|
||||||
|
__tablename__ = 'payloads'
|
||||||
|
|
||||||
|
external_id = Column('external_id', String(128), primary_key=True)
|
||||||
|
fiscal_receipt_number = Column('fiscal_receipt_number', Integer)
|
||||||
|
shift_number = Column('shift_number', Integer)
|
||||||
|
receipt_datetime = Column('receipt_datetime', String(length=128))
|
||||||
|
total = Column('total', Numeric(12, 2))
|
||||||
|
fn_number = Column('fn_number', String(length=128))
|
||||||
|
ecr_registration_number = Column(
|
||||||
|
'ecr_registration_number', String(length=128))
|
||||||
|
fiscal_document_number = Column('fiscal_document_number', Integer)
|
||||||
|
fiscal_document_attribute = Column('fiscal_document_attribute', Integer)
|
||||||
|
fns_site = Column('fns_site', String(length=128))
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
class Sell(Base):
|
||||||
|
__tablename__ = 'sells'
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
|
external_id = Column('external_id',String(128))
|
||||||
|
is_refund = Column('is_refund', Boolean)
|
||||||
|
service = Column('service', String(length=16))
|
||||||
|
timestamp = Column('timestamp', DateTime)
|
||||||
|
"""
|
319
kassa/new.py
Normal file
319
kassa/new.py
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
from time import sleep
|
||||||
|
from typing import Dict, List, Tuple
|
||||||
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
from sqlalchemy import create_engine, Table, Column, engine
|
||||||
|
from sqlalchemy.orm.session import Session
|
||||||
|
from sqlalchemy.orm import query, sessionmaker
|
||||||
|
from sqlalchemy.types import BigInteger, Integer, String, Numeric, Boolean, DateTime
|
||||||
|
from sqlalchemy.sql.sqltypes import DateTime
|
||||||
|
from sqlalchemy import desc, cast, case, func
|
||||||
|
import schemas
|
||||||
|
import models
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
Base = declarative_base()
|
||||||
|
metadata = Base.metadata
|
||||||
|
|
||||||
|
|
||||||
|
class PaymentDetails(Base):
|
||||||
|
__tablename__ = "payment_details"
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
|
external_id = Column(String(36), nullable=False, index=True)
|
||||||
|
is_refund = Column(Boolean, nullable=False, index=True)
|
||||||
|
is_taken = Column(Boolean, nullable=False, index=True)
|
||||||
|
added_date = Column(DateTime, nullable=True,
|
||||||
|
default=datetime.datetime.now())
|
||||||
|
# class PaymentDetailsBaseModel(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
|
class DBEngine:
|
||||||
|
def __init__(self, server, dbname, user, password):
|
||||||
|
self.dbname = dbname
|
||||||
|
self.user = user
|
||||||
|
self.password = password
|
||||||
|
self.server = server
|
||||||
|
self.get_mssql_engine()
|
||||||
|
|
||||||
|
def get_mssql_engine(self):
|
||||||
|
query = f'mssql+pyodbc://{self.user}:{self.password}@{self.server}/{self.dbname}?driver=SQL+Server'
|
||||||
|
self.engine = create_engine(
|
||||||
|
query, connect_args={'check_same_thread': False})
|
||||||
|
|
||||||
|
def get_table(self, tablename: str) -> Table:
|
||||||
|
self.metadata = Base.metadata
|
||||||
|
self.metadata.reflect(bind=self.engine)
|
||||||
|
return Table(tablename, self.metadata, schema=self.dbname+'.dbo', autoload=True, autoload_with=self.engine)
|
||||||
|
|
||||||
|
def get_columns(self, tablename: str, columns: List[str] = None, labels: Dict = None) -> List[Column]:
|
||||||
|
table = self.get_table(tablename)
|
||||||
|
if not labels:
|
||||||
|
labels = {}
|
||||||
|
if columns:
|
||||||
|
|
||||||
|
lst = [(table.c.get(column)).label(labels.get(column, column) or column)
|
||||||
|
for column in columns]
|
||||||
|
return lst
|
||||||
|
return table.c.items()
|
||||||
|
|
||||||
|
def get_db(self):
|
||||||
|
db = Session(autocommit=False, autoflush=False, bind=self.engine)
|
||||||
|
try:
|
||||||
|
yield db
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
|
def get_payment_details(db: Session, engine_class: DBEngine):
|
||||||
|
pd = engine_class.get_table('payment_details')
|
||||||
|
external_id, is_refund, is_taken = engine_class.get_columns(
|
||||||
|
'payment_details', ['external_id', 'is_refund', 'is_taken'])
|
||||||
|
query = db.query(pd).filter(is_taken == 0).with_entities(
|
||||||
|
external_id, is_refund, is_taken).distinct().order_by(external_id, desc(is_refund))
|
||||||
|
return query
|
||||||
|
|
||||||
|
|
||||||
|
def update_payment_details(db: Session, engine_class: DBEngine, payment_details: Dict):
|
||||||
|
external_id_value = payment_details.get("external_id")
|
||||||
|
is_refund_value = payment_details.get("is_refund")
|
||||||
|
is_taken_value = payment_details.get("is_taken")
|
||||||
|
pd = engine_class.get_table('payment_details')
|
||||||
|
external_id, is_refund, is_taken = engine_class.get_columns(
|
||||||
|
'payment_details', ['external_id', 'is_refund', 'is_taken'])
|
||||||
|
query = db.query(pd).filter(external_id == external_id_value,
|
||||||
|
is_taken == is_taken_value, is_refund == is_refund_value)
|
||||||
|
query = query.update({'is_taken': True}, synchronize_session='fetch')
|
||||||
|
db.commit()
|
||||||
|
return query
|
||||||
|
|
||||||
|
|
||||||
|
def get_payment(db: Session, engine_class: DBEngine, payment_details: Tuple):
|
||||||
|
external_id_value, is_refund_value, is_taken_value = payment_details
|
||||||
|
pd = engine_class.get_table('payment_details')
|
||||||
|
external_id, is_refund, is_taken = engine_class.get_columns(
|
||||||
|
'payment_details', ['external_id', 'is_refund', 'is_taken'])
|
||||||
|
query = db.query(pd).filter(external_id == external_id_value,
|
||||||
|
is_taken == is_taken_value, is_refund == is_refund_value)
|
||||||
|
return query
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
#Место сбора запроса на items с заполнением по справочникам
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def get_payment_details_items(db: Session, engine_class: DBEngine, dict_engine: DBEngine, payment_details: Tuple):
|
||||||
|
payment = get_payment(
|
||||||
|
db, engine_class, payment_details).subquery('payment')
|
||||||
|
services = dict_engine.get_table('services')
|
||||||
|
units = dict_engine.get_table('units')
|
||||||
|
payment_method = dict_engine.get_table('payment_method')
|
||||||
|
payment_object = dict_engine.get_table('payment_object')
|
||||||
|
vats = dict_engine.get_table('payment_object_vat_type')
|
||||||
|
agents = dict_engine.get_table('agents')
|
||||||
|
company = dict_engine.get_table('providers')
|
||||||
|
query = db.query(
|
||||||
|
payment.c.external_id.label('external_id'),
|
||||||
|
services.c.sname.label('name'),
|
||||||
|
units.c["sname"].label('measurement_unit'),
|
||||||
|
payment.c.price.label('price'),
|
||||||
|
payment.c.quantity.label('quantity'),
|
||||||
|
payment.c.date_operation.label('date_operation'),
|
||||||
|
payment.c.phone.label('phone'),
|
||||||
|
company.c.inn,
|
||||||
|
payment.c.summa.label('sum'),
|
||||||
|
case(
|
||||||
|
(payment.c.payment_method.in_([5, 6, 7]), 3),
|
||||||
|
(payment.c.payment_method.in_([1, 2, 3]), 2),
|
||||||
|
(payment.c.payment_method == 4, 1)
|
||||||
|
).label("payment_group"),
|
||||||
|
payment_method.c["name"].label('payment_method'),
|
||||||
|
payment_object.c["name"].label('payment_object'),
|
||||||
|
vats.c["name"].label("vat"),
|
||||||
|
payment.c.agent_type.label('agent_info'),
|
||||||
|
case((payment.c.agent_type != None, payment.c.supplier_info),
|
||||||
|
else_=None).label('supplier_info'),
|
||||||
|
agents.c["inn"].label("supplier_inn"),
|
||||||
|
agents.c["name"].label("supplier_name")
|
||||||
|
).select_from(payment)\
|
||||||
|
.join(services, services.c["id_service"] == payment.c.id_item)\
|
||||||
|
.join(units, services.c["id_unit"] == units.c["id_unit"])\
|
||||||
|
.join(payment_method, payment.c.payment_method == payment_method.c["id"])\
|
||||||
|
.join(payment_object, payment.c.payment_object == payment_object.c["id"])\
|
||||||
|
.join(vats, payment.c.vat == vats.c["id"])\
|
||||||
|
.join(company, payment.c.id_company == company.c["id_provider"])\
|
||||||
|
.join(agents, payment.c.supplier_info == agents.c["id_agent"])
|
||||||
|
return query
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
#Функция для заполнения payments
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def get_payments(data: List):
|
||||||
|
d = {}
|
||||||
|
for row in data:
|
||||||
|
type_id = row.get("payment_group")
|
||||||
|
cur_sum = row.get("sum")
|
||||||
|
d[type_id] = cur_sum + d.get(type_id, 0.0)
|
||||||
|
res = [{'type': i[0], 'sum': i[1]} for i in d.items()]
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def get_token(db: Session, db_dict: DBEngine):
|
||||||
|
token_dict = db_dict.get_table("vAtolToken")
|
||||||
|
return token_dict.get("token")
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
#Функция для заполнения total
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def get_total(data: List):
|
||||||
|
total = 0.0
|
||||||
|
for i in data:
|
||||||
|
total += i.get("sum")
|
||||||
|
return total
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
#Функция для заполнения items в dicts
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def items_convert(data: query):
|
||||||
|
items = []
|
||||||
|
external_id = 0
|
||||||
|
total = 0.0
|
||||||
|
d = {}
|
||||||
|
payments = []
|
||||||
|
phone = ""
|
||||||
|
inn = 0
|
||||||
|
for row in data.all():
|
||||||
|
item = dict(row)
|
||||||
|
external_id = item.get("external_id")
|
||||||
|
item["vat"] = get_vat(item.get("vat"))
|
||||||
|
agent_info = item.pop("agent_info", None)
|
||||||
|
total += item.get("sum")
|
||||||
|
type_id = item.get("payment_group")
|
||||||
|
cur_sum = item.get("sum")
|
||||||
|
phone = item.get("phone", '+79111111111')
|
||||||
|
inn = int(item.get("inn"))
|
||||||
|
d[type_id] = cur_sum + d.get(type_id, 0.0)
|
||||||
|
if agent_info:
|
||||||
|
item["agent_info"] = {"type": agent_info}
|
||||||
|
item["supplier_info"] = {
|
||||||
|
"inn": item.pop("supplier_inn", None),
|
||||||
|
"name": item.pop("supplier_name", None)
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
for i in ["supplier_info", 'supplier_inn', 'supplier_name']:
|
||||||
|
del item[i]
|
||||||
|
items.append(item)
|
||||||
|
payments = [{'type': i[0], 'sum': i[1]} for i in d.items()]
|
||||||
|
client = get_client(phone)
|
||||||
|
company = get_company(inn)
|
||||||
|
return external_id, items, payments, client, company, total
|
||||||
|
|
||||||
|
|
||||||
|
def get_company(inn: int):
|
||||||
|
company = {}
|
||||||
|
company['inn'] = inn
|
||||||
|
company['email'] = 'ocnkp@jkhsakha.ru'
|
||||||
|
company['payment_address'] = 'http://jkhsakha.ru/'
|
||||||
|
company['sno'] = 'osn'
|
||||||
|
return company
|
||||||
|
|
||||||
|
|
||||||
|
def get_receipt(data: query):
|
||||||
|
receipt = {}
|
||||||
|
external_id = 0
|
||||||
|
external_id, items, payments, client, company, total = items_convert(
|
||||||
|
data)
|
||||||
|
receipt['client'] = client
|
||||||
|
receipt["payments"] = payments
|
||||||
|
receipt["company"] = company
|
||||||
|
receipt['items'] = items
|
||||||
|
receipt['total'] = total
|
||||||
|
return external_id, receipt
|
||||||
|
|
||||||
|
|
||||||
|
def get_sell(data: query):
|
||||||
|
sell = {}
|
||||||
|
current_datetime = datetime.datetime.now()
|
||||||
|
external_id, sell['receipt'] = get_receipt(data)
|
||||||
|
sell["timestamp"] = current_datetime.strftime(
|
||||||
|
'%d.%m.%Y %H:%M:%S')
|
||||||
|
sell["external_id"] = external_id
|
||||||
|
sell["service"] = {
|
||||||
|
'callback_url': f"http://api.jkhsakha.ru/kassa/{external_id}"
|
||||||
|
}
|
||||||
|
return sell
|
||||||
|
|
||||||
|
|
||||||
|
def get_client(phone: str):
|
||||||
|
return {
|
||||||
|
'phone': phone
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_vat(vat: str):
|
||||||
|
return {'type': vat}
|
||||||
|
|
||||||
|
|
||||||
|
def add_atol(db: Session, engine: DBEngine, atol: Dict):
|
||||||
|
aa = engine.get_table("Atol")
|
||||||
|
a = aa.insert().values(atol)
|
||||||
|
db.execute(a)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def add_doc(sell: schemas.Sell, is_refund):
|
||||||
|
from databases import SessionLocal
|
||||||
|
from atol import Atol
|
||||||
|
atol_model = Atol
|
||||||
|
session = SessionLocal()
|
||||||
|
a = Atol.set_sell(atol_model, sell, is_refund)
|
||||||
|
check = models.Atol(**a)
|
||||||
|
session.add(check)
|
||||||
|
session.commit()
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
|
||||||
|
def get_payment():
|
||||||
|
server = 'Sanctuary'
|
||||||
|
user = 'sa'
|
||||||
|
password = '159357'
|
||||||
|
dbname = 'fz54_details'
|
||||||
|
db_dicts_name = 'fz54'
|
||||||
|
db = DBEngine(server, dbname, user, password)
|
||||||
|
db_dicts = DBEngine(server, db_dicts_name, user, password)
|
||||||
|
session = Session(autocommit=False, autoflush=False, bind=db.engine)
|
||||||
|
payment = get_payment_details(session, db).first()
|
||||||
|
if payment:
|
||||||
|
payments = get_payment_details_items(session, db, db_dicts, payment)
|
||||||
|
body = get_sell(payments)
|
||||||
|
sell = schemas.Sell(**body)
|
||||||
|
payment = dict(payment)
|
||||||
|
atol = {
|
||||||
|
"external_id": payment.get("external_id"),
|
||||||
|
"is_refund": payment.get("is_refund"),
|
||||||
|
"is_taken": payment.get("is_taken"),
|
||||||
|
"body": str(body)
|
||||||
|
}
|
||||||
|
add_atol(session, db, atol)
|
||||||
|
update_payment_details(session, db, payment)
|
||||||
|
return sell, payment.get("is_refund")
|
||||||
|
return False, False
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
while True:
|
||||||
|
payment, is_refund = get_payment()
|
||||||
|
if payment == False:
|
||||||
|
break
|
||||||
|
sleep(1)
|
||||||
|
add_doc(sell=payment, is_refund=is_refund)
|
||||||
|
break
|
222
kassa/schemas.py
Normal file
222
kassa/schemas.py
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
from ast import Try
|
||||||
|
from typing import List, Optional, Dict
|
||||||
|
from pydantic import BaseModel, Field, confloat, constr
|
||||||
|
from sqlalchemy.sql.sqltypes import Boolean, DateTime
|
||||||
|
from sqlalchemy.sql.sqltypes import DateTime
|
||||||
|
|
||||||
|
|
||||||
|
class SumNumberTwoFormat(BaseModel):
|
||||||
|
__root__: Optional[confloat(ge=0.0, le=100000000.0, multiple_of=0.01)]
|
||||||
|
|
||||||
|
|
||||||
|
class NumberPrice(BaseModel):
|
||||||
|
__root__: confloat(ge=0.0, le=42949673.0, multiple_of=0.01)
|
||||||
|
|
||||||
|
|
||||||
|
class PhoneNumber(BaseModel):
|
||||||
|
__root__: constr(regex=r'^([^\s\\]{0,17}|\+[^\s\\]{1,18})$')
|
||||||
|
|
||||||
|
|
||||||
|
class NumberTwoFormat(BaseModel):
|
||||||
|
__root__: confloat(ge=0.0, le=100000000.0, multiple_of=0.01)
|
||||||
|
|
||||||
|
|
||||||
|
class NumberThreeFormat(BaseModel):
|
||||||
|
__root__: confloat(ge=0.0, le=100000.0, multiple_of=0.001)
|
||||||
|
|
||||||
|
|
||||||
|
class Service(BaseModel):
|
||||||
|
callback_url: Optional[constr(max_length=256)] = None
|
||||||
|
|
||||||
|
|
||||||
|
class Warnings(BaseModel):
|
||||||
|
callback_url: str = None
|
||||||
|
|
||||||
|
|
||||||
|
class PayingAgent(BaseModel):
|
||||||
|
operation: Optional[str] = None
|
||||||
|
phones: Optional[List[PhoneNumber]] = None
|
||||||
|
|
||||||
|
|
||||||
|
class SupplierInfo(BaseModel):
|
||||||
|
phones: Optional[List[PhoneNumber]] = None
|
||||||
|
name: Optional[str] = None
|
||||||
|
inn: Optional[str] = None
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class ReceivePaymentsOperator(BaseModel):
|
||||||
|
phones: Optional[List[PhoneNumber]] = None
|
||||||
|
|
||||||
|
|
||||||
|
class MoneyTransferOperator(BaseModel):
|
||||||
|
phones: Optional[List[PhoneNumber]] = None
|
||||||
|
name: Optional[str] = None
|
||||||
|
address: Optional[str] = None
|
||||||
|
inn: Optional[constr(regex=r'(^[0-9]{10}$)|(^[0-9]{12}$)')] = None
|
||||||
|
|
||||||
|
|
||||||
|
class Company(BaseModel):
|
||||||
|
email: Optional[constr(max_length=64)] = None
|
||||||
|
sno: Optional[str] = None
|
||||||
|
inn: constr(max_length=12)
|
||||||
|
payment_address: constr(max_length=256)
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class ClientItem(BaseModel):
|
||||||
|
email: constr(max_length=64) = None
|
||||||
|
phone: Optional[constr(max_length=64)] = None
|
||||||
|
|
||||||
|
|
||||||
|
class AdditionalUserProps(BaseModel):
|
||||||
|
name: constr(max_length=64)
|
||||||
|
value: constr(max_length=256)
|
||||||
|
|
||||||
|
|
||||||
|
class AgentInfo(BaseModel):
|
||||||
|
type: Optional[str] = None
|
||||||
|
paying_agent: Optional[PayingAgent] = None
|
||||||
|
receive_payments_operator: Optional[ReceivePaymentsOperator] = None
|
||||||
|
money_transfer_operator: Optional[MoneyTransferOperator] = None
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class Error(BaseModel):
|
||||||
|
error_id: Optional[str] = None
|
||||||
|
code: int
|
||||||
|
text: str
|
||||||
|
type: Optional[str] = None
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class Payload(BaseModel):
|
||||||
|
fiscal_receipt_number: int
|
||||||
|
shift_number: int
|
||||||
|
receipt_datetime: str
|
||||||
|
total: float
|
||||||
|
fn_number: str
|
||||||
|
ecr_registration_number: str
|
||||||
|
fiscal_document_number: int
|
||||||
|
fiscal_document_attribute: int
|
||||||
|
fns_site: str
|
||||||
|
|
||||||
|
|
||||||
|
class Vat(BaseModel):
|
||||||
|
type: Optional[str] = None
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class CorrectionInfo(BaseModel):
|
||||||
|
type: str
|
||||||
|
base_date: str
|
||||||
|
base_number: str
|
||||||
|
|
||||||
|
|
||||||
|
class Payment(BaseModel):
|
||||||
|
type: int
|
||||||
|
sum: SumNumberTwoFormat
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class Item(BaseModel):
|
||||||
|
name: str
|
||||||
|
price: NumberPrice
|
||||||
|
quantity: NumberThreeFormat
|
||||||
|
sum: SumNumberTwoFormat
|
||||||
|
measurement_unit: Optional[constr(max_length=16)] = None
|
||||||
|
payment_method: Optional[str] = None
|
||||||
|
payment_object: Optional[str] = None
|
||||||
|
nomenclature_code: Optional[str] = None
|
||||||
|
vat: Optional[Vat] = None
|
||||||
|
agent_info: Optional[AgentInfo] = None
|
||||||
|
supplier_info: Optional[SupplierInfo] = None
|
||||||
|
user_data: Optional[constr(max_length=64)] = None
|
||||||
|
excise: Optional[confloat(ge=0.0)] = None
|
||||||
|
country_code: Optional[constr(
|
||||||
|
regex=r'^[0-9]*$', min_length=1, max_length=3)] = None
|
||||||
|
declaration_number: Optional[constr(min_length=1, max_length=32)] = None
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class Receipt(BaseModel):
|
||||||
|
client: ClientItem
|
||||||
|
company: Company
|
||||||
|
agent_info: Optional[AgentInfo] = None
|
||||||
|
supplier_info: Optional[SupplierInfo] = None
|
||||||
|
items: List[Item] = Field(..., min_items=1)
|
||||||
|
payments: List[Payment] = Field(..., max_items=10, min_items=1)
|
||||||
|
vats: Optional[List[Vat]] = Field(None, max_items=6, min_items=1)
|
||||||
|
total: NumberTwoFormat
|
||||||
|
additional_check_props: Optional[constr(max_length=16)] = None
|
||||||
|
cashier: Optional[constr(max_length=64)] = None
|
||||||
|
additional_user_props: Optional[AdditionalUserProps] = None
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class Correction(BaseModel):
|
||||||
|
company: Company
|
||||||
|
cashier: Optional[constr(max_length=64)] = None
|
||||||
|
correction_info: CorrectionInfo
|
||||||
|
payments: List[int] = Field(..., max_items=10, min_items=1)
|
||||||
|
vats: List[Vat] = Field(..., max_items=6, min_items=1)
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class Doc(BaseModel):
|
||||||
|
uuid: str
|
||||||
|
timestamp: str
|
||||||
|
group_code: str
|
||||||
|
daemon_code: str
|
||||||
|
device_code: str
|
||||||
|
external_id: Optional[str] = None
|
||||||
|
callback_url: Optional[str] = None
|
||||||
|
status: Optional[str] = None
|
||||||
|
error: Error = None
|
||||||
|
warnings: Optional[Warnings] = None
|
||||||
|
payload: Payload = None
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class Sell(BaseModel):
|
||||||
|
external_id: constr(max_length=128)
|
||||||
|
receipt: Receipt
|
||||||
|
service: Optional[Service] = None
|
||||||
|
timestamp: str = None
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
arbitrary_types_allowed = True
|
||||||
|
|
||||||
|
|
||||||
|
class SellCreate(Sell):
|
||||||
|
is_refund: bool
|
||||||
|
|
||||||
|
|
||||||
|
class SellShow(SellCreate):
|
||||||
|
id: int
|
||||||
|
|
||||||
|
|
||||||
|
class Correction(BaseModel):
|
||||||
|
timestamp: str
|
||||||
|
external_id: constr(max_length=128)
|
||||||
|
service: Optional[Service] = None
|
32
main.py
32
main.py
@ -3,14 +3,15 @@ from fastapi.middleware import Middleware
|
|||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from kv import kv
|
from kv import kv
|
||||||
from auth import auth
|
from auth import auth
|
||||||
|
from kassa import kassa
|
||||||
import uvicorn
|
import uvicorn
|
||||||
|
|
||||||
middleware = [Middleware(
|
middleware = [Middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
allow_origins = ['*'],
|
allow_origins=['*'],
|
||||||
allow_credentials = True,
|
allow_credentials=True,
|
||||||
allow_methods = ['*'],
|
allow_methods=['*'],
|
||||||
allow_headers = ['*'],
|
allow_headers=['*'],
|
||||||
)]
|
)]
|
||||||
|
|
||||||
app = FastAPI(middleware=middleware)
|
app = FastAPI(middleware=middleware)
|
||||||
@ -18,15 +19,26 @@ app = FastAPI(middleware=middleware)
|
|||||||
|
|
||||||
@app.get('/hello')
|
@app.get('/hello')
|
||||||
async def say_hello():
|
async def say_hello():
|
||||||
return { "text": "Hello!" }
|
return {"text": "Hello!"}
|
||||||
|
|
||||||
app.include_router(
|
app.include_router(
|
||||||
router = auth.router,
|
router=auth.router,
|
||||||
prefix= '/auth',
|
prefix='/auth',
|
||||||
|
tags=['Авторизация'],
|
||||||
|
responses={404: {"description": "Not found"}}
|
||||||
|
)
|
||||||
|
app.include_router(
|
||||||
|
router=kv.router,
|
||||||
|
prefix='/kv',
|
||||||
|
tags=['Кварплата'],
|
||||||
|
responses={404: {"description": "Not found"}}
|
||||||
|
)
|
||||||
|
app.include_router(
|
||||||
|
router=kassa.router,
|
||||||
|
prefix='/kassa',
|
||||||
|
tags=['Касса Атол'],
|
||||||
responses={404: {"description": "Not found"}}
|
responses={404: {"description": "Not found"}}
|
||||||
)
|
)
|
||||||
app.include_router(router = kv.router, prefix = '/kv',tags=['Кварплата'], responses={404: {"description": "Not found"}})
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
uvicorn.run("main:app", host = "0.0.0.0", port = 5000)
|
uvicorn.run("main:app", host="0.0.0.0", port=5000)
|
||||||
|
Reference in New Issue
Block a user