Tally integration on odoo - python

How can I export tax analysis in invoice in tally to xml request?
url1 = "http://localhost:9000"
xml = "<ENVELOPE><HEADER><VERSION>1</VERSION><TALLYREQUEST>EXPORT</TALLYREQUEST><TYPE>DATA</TYPE>"
xml += "<ID>VoucherRegister</ID></HEADER><BODY><DESC><STATICVARIABLES>"
xml += "<EXPLODEVNUM>Yes</EXPLODEVNUM><ISVATDUTYPAID>Yes</ISVATDUTYPAID><DBINVEXPLODEFLAG>Yes</DBINVEXPLODEFLAG>"
xml+="<DBBILLEXPLODEFLAG>Yes</DBBILLEXPLODEFLAG><SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT><SVFROMDATE Type='DATE'>"+self.startdate+"</SVFROMDATE><SVTODATE Type='DATE'>"+self.enddate+"</SVTODATE><VOUCHERTYPENAME>"+self.sale_name+"</VOUCHERTYPENAME><EXPLODEFLAG>Yes</EXPLODEFLAG><REPORTNAME>Ledger Cost Breakup</REPORTNAME></STATICVARIABLES>"
xml += "<TDL><TDLMESSAGE><COLLECTION><FETCH>GSTDetails.LIST</FETCH></COLLECTION></TDLMESSAGE></TDL></DESC></BODY></ENVELOPE>"
req = requests.post(url = url1,data=xml)
# res = req.text.decode("UTF-8")
response = req.text.strip().replace("&","&")
# scrubbedXML = re.sub('&.+[0-9]+;', '', response)
# print(response)
responseXML = Et.fromstring(response)
values=database.data()
print(values)
url_odoo=values['urls']
db_odoo=values['database']
email_odoo=values['email']
password_odoo=values['password']
print(url_odoo)
url=url_odoo
db=db_odoo
username=email_odoo
password=password_odoo
common = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url),allow_none=True)
uid = common.authenticate(db, username, password, {})
models = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url),allow_none=True)
for vch in responseXML.findall("./BODY/DATA/TALLYMESSAGE/VOUCHER"):
mylist=[]
mylist2=[]
myliist3=[]
stockslist=[]
amountlist=[]
quantitylist=[]
roundofflist=[]
discountlist=[]
try:
if len(vch.findall('INVENTORYENTRIES.LIST'))>=0:
try:
# stk = vch.findall("INVENTORYENTRIES.LIST").__getitem__(0).find("STOCKITEMNAME").text
for stockss in vch.findall("INVENTORYENTRIES.LIST"):
stks=stockss.find('STOCKITEMNAME').text
# print(stks)
stockslist.append(stks)
except:
stk='na'
pass
try:
for discoun in vch.findall("INVENTORYENTRIES.LIST"):
disc=float(discoun.find('DISCOUNT').text)
print(disc)
discountlist.append(disc)
# stockslist.append(stks)
except:
disc=0
discountlist.append(disc)
pass
try:
# rt = vch.findall("INVENTORYENTRIES.LIST").__getitem__(0).find("RATE").text
for rates in vch.findall('INVENTORYENTRIES.LIST'):
perrattes=rates.find('RATE').text
ratee=(re.findall(r'-?\d+\.?\d*', perrattes))
for s in ratee:
perrate=float(s)
# print(perrate)
amountlist.append(perrate)
except:
perrate=0
# print(perrate)
pass
try:
# Ktk = vch.findall("INVENTORYENTRIES.LIST").__getitem__(0).find("BILLEDQTY").text
for ktks in vch.findall('INVENTORYENTRIES.LIST'):
ktk= ktks.find('BILLEDQTY').text
billedqu=(re.findall(r'-?\d+\.?\d*', ktk))
for b in billedqu:
quan=float(b)
# print(quan)
quantitylist.append(quan)
except:
quan=1.0
quantitylist.append(quan)
# print(quan)
except:
continue
if len(vch.findall("LEDGERENTRIES.LIST"))>=0:
try:
for ro in vch.findall("LEDGERENTRIES.LIST"):
roundoff=ro.find('AMOUNT').text
round=float(roundoff)
if round>0 and round<1.0 or round< 0 and round>-1.0:
roff=float(round)
roundofflist.append(roff)
for items in vch.findall("LEDGERENTRIES.LIST"):
vall=items.find('LEDGERNAME').text
mylist.append(vall)
print(mylist)
except:
amount=0
toname='na'
# print(toname)
pass
else:
try:
amount = vch.findall("ALLLEDGERENTRIES.LIST").__getitem__(0).find("LEDGERNAME").text
except:
amount='na'
pass
try:
vch_dt=vch.find("DATE").text
vch_date=self.change_date_format(vch_dt)
except:
vch_date='na'
pass
try:
vch_led= vch.find("VOUCHERTYPENAME").text
print(vch_led)
except:
vch_led='na'
pass
try:
vch_type= vch.find("VOUCHERNUMBER").text
print(vch_type)
except:
vch_type='na'
pass
try:
vch_no= vch.find("PARTYLEDGERNAME").text
except:
vch_no= 'na'
pass
print(mylist)
try:
del mylist[0]
except:
pass
for valll in mylist:
pid=models.execute_kw(db, uid, password, 'account.tax','search',[[['name', '=',valll]]])
print(pid)
mylist2.append(pid)
# del mylist2[0]
print(mylist2,'check')
for value1 in mylist2:
try:
val2=value1[0]
except:
pass
try:
myliist3.append(val2)
print(myliist3)
except:
pass
xid=models.execute_kw(db, uid, password, 'account.invoice','search_count',[[['origin', '=', vch_type]]])
# print(xid)
lid=models.execute_kw(db, uid, password, 'account.invoice','search',[[['origin', '=', vch_type]]])
try:
sid=models.execute_kw(db,uid, password, 'res.partner','search',[[['name', '=', vch_no]]])
print(sid)
except:
continue
# print(sid)
# print(mid)
print(stockslist)
print(amountlist)
print(quantitylist)
for vill in sid:
if xid>=1:
continue
else:
rslt =models.execute_kw(db, uid, password, 'account.invoice','create',[{'partner_id': vill,
'date_invoice':vch_date,'date_due':vch_date,'journal_id':1,'state':'draft','origin':vch_type}])
print(rslt)
for st,ratt,quant,discon in zip(stockslist,amountlist,quantitylist,discountlist):
# rateval=calculate_rate(ratt,quant)
ratevals=float(ratt)
mid=models.execute_kw(db,uid, password, 'product.product','search',[[['name', '=', st]]])
print(mid,'bye')
for stockna in mid:
stock=stockna
va=models.execute_kw(db, uid, password,'product.product', 'read',[mid], {'fields': [ 'taxes_id']})
print(va)
for taxed in va:
taxfv=taxed['taxes_id']
print(taxfv,'hi')
if taxfv==[]:
taxfv=myliist3
# Oid=models.execute_kw(db, uid, password, 'account.tax','search',[[['name', '=','CGST'],['type_tax_use','=','sale']]])
# Otd=models.execute_kw(db, uid, password, 'account.tax','search',[[['name', '=','SGST'],['type_tax_use','=','sale']]])
# Oid=Oid+Otd
# taxfv=Oidk
# print(Oid)
else:
taxfv==taxfv
print(taxfv,'final')
res=models.execute_kw(db, uid, password, 'account.invoice','write',[[rslt],{'invoice_line_ids':
[(0,4, {'name': st,
'origin': vch_type,
'account_id':31,
'price_unit': ratevals,
'quantity': quant,
'is_rounding_line': True,
'discount':discon,
'uom_id': 1,
'product_id': stock,
'invoice_line_tax_ids': [[6,True, taxfv]]
}
)
]
}
]
)
res=models.execute_kw(db, uid, password, 'account.invoice','compute_taxes',[rslt])
# print(roundofflist)
for ron in roundofflist:
round=models.execute_kw(db, uid, password, 'account.invoice','write',[[rslt],{'invoice_line_ids':[(0,4, {'name': 'Rounded off',
'account_id': 284,
'price_unit': ron,
'quantity': 1})]}])
vali=models.execute_kw(db, uid, password, 'account.invoice','action_invoice_open',[rslt])

Related

Comparing id betwen config value and API output

I want to check if the fields 'id' and 'folder_id' of api_response equal certain values (here, respectively 25 and 17). If it does, return true, else return false. My problem is that my script returns false when it should return true because the fields id and folder_id are correct.
Here is my code:
SendInBlueAPI = config.get('Config','SendInBlueAPI')
SendInBlueFolderID = config.get('Config','SendInBlueFolderID')
SendInBlueListID = config.get('Config','SendInBlueListID')
## Checking if list exists in SendInBlue
configuration = sib_api_v3_sdk.Configuration()
configuration.api_key['api-key'] = '%s' % (SendInBlueAPI)
api_instance = sib_api_v3_sdk.ListsApi(sib_api_v3_sdk.ApiClient(configuration))
list_id = SendInBlueListID
try:
api_response = api_instance.get_list(list_id)
if api_response.id == SendInBlueListID and api_response.folder_id == SendInBlueFolderID:
print(True)
else:
print(False)
except ApiException as e:
print("Exception when calling ListsApi->get_list: %s\n" % e)
This is the output of api_response:
{'campaign_stats': None,
'created_at': '2023-01-16T10:07:47.000+01:00',
'dynamic_list': False,
'folder_id': 17,
'id': 25,
'name': 'My list',
'total_blacklisted': 2,
'total_subscribers': 244,
'unique_subscribers': 246}
And here is my config file :
[Config]
SendInBlueAPI = MY_API_KEY
SendInBlueFolderID = 17
SendInBlueListID = 25

OCPP 1.6 Remote Start Transaction

This is our CentralSystem.py
We have a LIVE charger configured to connect to our websocket
Ex - ws://HostName:Port/Charger Serial Number
As soon as the Charger is connected to our central system, it automatically sends us the following:
Charge point /D5200372001000010101 connected
INFO:ocpp:D5200372001000010101: receive message [2,"530","Heartbeat",{}]
Heartbeat
INFO:ocpp:D5200372001000010101: send [3,"530",{"currentTime":"2022-06-10T10:43:26Z"}]
INFO:ocpp:D5200372001000010101: receive message [2,"531","Heartbeat",{}]
Heartbeat
Issue 1 - We receive the heartbeat every 2mins but do not see anything for BootNotification and Status Notification when no vehicle is connected.
However, when the vehicle is connected, we do see a Status Notification and Heartbeats.
Issue 2 - Now, we have a mobile app that is built using Flutter which should allow us to enable "Remote Start Transaction". What is the best way to achieve this? Should we connect to the same websocket endpoint and call RemoteStartTransaction.
import asyncio
import logging
from asyncio import constants
import websockets
from datetime import datetime, timezone
from ocpp.routing import on
from ocpp.v16 import ChargePoint as cp
from ocpp.v16.enums import Action, RegistrationStatus, RemoteStartStopStatus
import ocpp.v16.enums as enums
from ocpp.v16 import call_result, call
import requests
logging.basicConfig(level=logging.INFO)
class ChargePoint(cp):
chargingProfile = {}
#on(Action.RemoteStartTransaction)
async def on_remote_start(self, id_tag, connector_id):
print("remotely starting")
return await self.remote_start_transaction()
#on(Action.BootNotification)
def on_boot_notification(self, charge_point_vendor, charge_point_model, **kwargs):
print("Boot Notification")
return call_result.BootNotificationPayload(
# current_time=datetime.utcnow().isoformat() + 'Z',
current_time=datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S') + "Z",
interval=100,
status=RegistrationStatus.accepted
)
#on(Action.StatusNotification)
def on_status_notification(self, connector_id, error_code, status, **kwargs):
print("Status Notification")
return call_result.StatusNotificationPayload()
#on(Action.Heartbeat)
def on_heartbeat(self):
print("Heartbeat")
return call_result.HeartbeatPayload(
current_time=datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S') + "Z"
)
#on(Action.Authorize)
def on_authorize(self, id_tag):
print("Authorize")
query = {'access_token': 'masterKey'}
response = requests.get('http://ec2-13-233-102-233.ap-south-1.compute.amazonaws.com:3000/chargersOnboarding/',
params=query)
data = response.json()
isFound = "false"
status = ""
for item in data['rows']:
if item['RFID'] == id_tag:
isFound = "true"
if item['status'] == 0:
status = "Accepted"
else:
status = "Expired"
break
else:
continue
if isFound == "true":
print("Authorized")
return call_result.AuthorizePayload(
id_tag_info={
# "expiryDate": "2022-02-04T13:00:00.21Z",
"expiryDate": "2023-05-19T13:00:00.21Z",
"parentIdTag": id_tag,
"status": status
},
)
else:
print("Not Authorized")
return call_result.AuthorizePayload(
id_tag_info={
"expiryDate": "",
"parentIdTag": id_tag,
"status": "Invalid"
},
)
#on(Action.StartTransaction)
def on_start_transaction(self, connector_id, id_tag, meter_start, timestamp, **kwargs):
print("START TRANSACTION COMING FROM CHARGER")
query = {'access_token': 'masterKey'}
response = requests.get('http://ec2-13-233-102-233.ap-south-1.compute.amazonaws.com:3000/chargersOnboarding/',
params=query)
data = response.json()
isFound = "false"
status = ""
for item in data['rows']:
if item['RFID'] == id_tag:
isFound = "true"
if item['status'] == 0:
status = "Accepted"
else:
status = "Expired"
break
else:
continue
if isFound == "true":
return call_result.StartTransactionPayload(
id_tag_info={
# "expiryDate": "2022-02-04T13:00:00.21Z",
"expiryDate": "2023-05-19T13:00:00.21Z",
"parentIdTag": id_tag,
"status": status
},
transaction_id=int(1)
)
else:
print("Not Authorized")
return call_result.StartTransactionPayload(
id_tag_info={
"expiryDate": "",
"parentIdTag": id_tag,
"status": "Invalid"
},
transaction_id=int(1)
)
#on(Action.StopTransaction)
def on_stop_transaction(self, transaction_id, timestamp, meter_stop, id_tag, **kwargs):
query = {'access_token': 'masterKey'}
response = requests.get('http://ec2-13-233-102-233.ap-south-1.compute.amazonaws.com:3000/chargersOnboarding/',
params=query)
data = response.json()
isFound = "false"
status = ""
for item in data['rows']:
if item['RFID'] == id_tag:
isFound = "true"
if item['status'] == 0:
status = "Accepted"
else:
status = "Expired"
break
else:
continue
if isFound == "true":
return call_result.StopTransactionPayload(
id_tag_info={
# "expiryDate": "2022-02-04T13:00:00.21Z",
"expiryDate": "2023-05-19T13:00:00.21Z",
"parentIdTag": id_tag,
"status": status
},
# transaction_id=int(1)
)
else:
print("Not Authorized")
return call_result.StopTransactionPayload(
id_tag_info={
"expiryDate": "",
"parentIdTag": id_tag,
"status": "Invalid"
},
transaction_id=int(1)
)
#on(Action.MeterValues)
def on_meter_value(self, **kwargs):
return call_result.MeterValuesPayload()
#on(Action.DataTransfer)
def on_data_transfer(self, vendor_id, message_id, data):
return call_result.DataTransferPayload(
status='Accepted'
)
#on(Action.ChangeAvailability)
def on_change_availabilty(self, connector_id, type):
return call_result.ChangeAvailabilityPayload(
status='Accepted'
)
async def send_limitation(self, limit):
response = await self.call(call.SetChargingProfilePayload(
connector_id=0,
cs_charging_profiles={
'chargingProfileId': 1,
'stackLevel': 0,
'chargingProfilePurpose': enums.ChargingProfilePurposeType.chargepointmaxprofile,
'chargingProfileKind': enums.ChargingProfileKindType.absolute,
'chargingSchedule': {
'startSchedule': datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S') + "Z",
'chargingRateUnit': enums.ChargingRateUnitType.amps,
'chargingSchedulePeriod': [{
'startPeriod': 0,
'limit': limit
}]
}
}
))
print("SEND Limitation")
print(response)
async def remote_start_transaction(self):
obj = {
'chargingProfileId': 1,
'stackLevel': 0,
'chargingProfilePurpose': enums.ChargingProfilePurposeType.chargepointmaxprofile,
'chargingProfileKind': enums.ChargingProfileKindType.absolute,
'chargingSchedule': {
'startSchedule': datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S') + "Z",
'chargingRateUnit': enums.ChargingRateUnitType.amps,
'chargingSchedulePeriod': [{
'startPeriod': 0,
'limit': 8.0
}]
},
}
print("REMOTE START!!!")
request = call.RemoteStartTransactionPayload(
id_tag='5C1DEA5A',
charging_profile=obj,
connector_id=1
)
response = await self.call(request)
print(response)
if response.status == RemoteStartStopStatus.accepted:
print("Transaction Started!!!")
else:
print("Transaction Failed to Start!!!")
print(response.status)
# websockets.send("Transaction Started!!!")
async def remote_stop_transaction(self):
print("REMOTE STOP!!!")
request = call.RemoteStopTransactionPayload(
transaction_id=1
)
response = await self.call(request)
if response.status == RemoteStartStopStatus.accepted:
print("Stopping transaction")
# websockets.send("Transaction Stopped!!!")
async def on_connect(websocket, path):
charge_point_id = path.strip('/')
cp = ChargePoint(charge_point_id, websocket)
try:
print(f'Charge point {path} connected')
await asyncio.gather(cp.start())
except websockets.exceptions.ConnectionClosed:
print(f"Charge Point {path} disconnected")
async def main():
server = await websockets.serve(
on_connect,
'0.0.0.0',
9000,
subprotocols=['ocpp1.6'],
ping_interval=None,
ping_timeout=None
)
logging.info("Server Started listening to new connections...")
await server.wait_closed()
if __name__ == '__main__':
asyncio.run(main())
> async def send_heartbeat(self, interval):
> request = call.HeartbeatPayload()
> while True:
> await self.call(request)
> await asyncio.sleep(interval)
>
> await asyncio.gather(cp.start(), cp.send_heartbeat(10))

How can i drop table after finish my scenario?

i have a problem with drop table after finish my scenario
when I try to delete using db.drop_table(Routes, if_exists=False, with_all_data=False) or db.drop_table(Routes, if_exists=True, with_all_data=True)
i get an error
pony.orm.core.TransactionError: #db_session-decorated drop_table() function with ddl option cannot be called inside of another db_sessio
i try to delete using Routes.delete() and I got the same one
i read more documentation and i dont know how can i drop this table
my full code
import logging
import random
import requests
import vk_api
from pony.orm import db_session, rollback
from vk_api.bot_longpoll import VkBotLongPoll, VkBotEventType
import handlers
from models import UserState, Registration, Routes, db
try:
import settings
except ImportError:
exit('DO CP settings.py.default setting.py and set token')
log = logging.getLogger('bot')
def configure_logging():
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(logging.Formatter('%(levelname)s %(message)s'))
stream_handler.setLevel(logging.INFO)
log.addHandler(stream_handler)
file_handler = logging.FileHandler('bot.log')
file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
file_handler.setLevel(logging.DEBUG)
log.addHandler(file_handler)
class Bot:
"""
Echo bot for vk.com
Use python 3.7
"""
def __init__(self, group_id, token):
"""
:param group_id:group_id from group vk.com
:param token:secret key
"""
self.group_id = group_id
self.token = token
self.vk = vk_api.VkApi(token=self.token)
self.long_poller = VkBotLongPoll(self.vk, self.group_id)
self.api = self.vk.get_api()
def run(self):
"""run bot"""
for event in self.long_poller.listen():
try:
print(event)
self.on_event(event)
except Exception:
log.exception('ошибка в обработке события')
#db_session
def on_event(self, event):
"""
sends the message back, if message text
:param event: VKBotMessageEvent object
:return: None
"""
if event.type != VkBotEventType.MESSAGE_NEW:
log.info('пока не умеем работать с таким типом события %s', event.type)
return
user_id = event.message.peer_id
text = event.message.text
state = UserState.get(user_id=str(user_id))
if state is not None:
self.continue_scenario(text=text, state=state, user_id=user_id)
else:
# search intent, the user is found outside of the scenario
for intent in settings.INTENTS:
log.debug(f'User gets {intent}')
if any(token in text.lower() for token in intent['tokens']):
# run intent
if intent['answer']:
self.send_text(text_to_send=intent['answer'], user_id=user_id)
else:
self.start_scenario(scenario_name=intent['scenario'], user_id=user_id, text=text)
break
else:
self.send_text(text_to_send=settings.DEFAULT_ANSWER, user_id=user_id)
# функция отправки текста
def send_text(self, text_to_send, user_id):
self.api.messages.send(
message=text_to_send,
random_id=random.randint(0, 2 ** 20),
peer_id=user_id)
# функция отправки изображения
def send_image(self, image, user_id):
upload_url = self.api.photos.getMessagesUploadServer()['upload_url']
upload_data = requests.post(url=upload_url, files={'photo': ('image.png', image, 'image/png')}).json()
image_data = self.api.photos.saveMessagesPhoto(**upload_data)
owner_id = image_data[0]['owner_id']
media_id = image_data[0]['id']
attachment = f'photo{owner_id}_{media_id}'
self.api.messages.send(
attachment=attachment,
random_id=random.randint(0, 2 ** 20),
peer_id=user_id)
# функция отправки маршрутов
def send_routes(self, text_to_send, user_id):
self.api.messages.send(
message=text_to_send,
random_id=random.randint(0, 2 ** 20),
peer_id=user_id)
# шаг отправки
def send_step(self, step, user_id, text, context):
if 'text' in step:
self.send_text(text_to_send=step['text'].format(**context), user_id=user_id)
if 'image' in step:
handler = getattr(handlers, step['image'])
image = handler(text=text, context=context)
self.send_image(image=image, user_id=user_id)
if 'choice' in step:
handler = getattr(handlers, step['choice'])
choices = handler(text=text, context=context)
for i, choice in enumerate(choices, start=1):
city_from = context['city_from']
city_to = context['city_to']
flight_time = choice[city_from][city_to][0]
flight_board = choice[city_from][city_to][1]
flight_date = choice[city_from][city_to][2]
number_choice = str(i) + ') '
Routes(number_choice=number_choice, flight_time=flight_time, city_from=city_from, city_to=city_to,
flight_board=flight_board, flight_date=flight_date)
select = db.select('number_choice,flight_time,city_from,city_to,flight_board,flight_date FROM Routes')
text_to_send = ' '.join(select[0]) + '\n' + ' '.join(select[1]) + '\n' + ' '.join(
select[2]) + '\n' + ' '.join(
select[3]) + '\n' + ' '.join(select[4]) + '\n'
self.send_routes(text_to_send=text_to_send, user_id=user_id)
# начало сценария
def start_scenario(self, scenario_name, user_id, text):
scenario = settings.SCENARIOS[scenario_name]
first_step = scenario['first_step']
step = scenario['steps'][first_step]
self.send_step(step=step, user_id=user_id, text=text, context={})
UserState(user_id=str(user_id), scenario_name=scenario_name, step_name=first_step, context={})
# конец сценария
def continue_scenario(self, text, state, user_id):
steps = settings.SCENARIOS[state.scenario_name]['steps']
step = steps[state.step_name]
handler = getattr(handlers, step['handler'])
if handler(text=text, context=state.context):
# next_step
if step['handler'] != 'handler_answer':
self.walking_through_scenario(state=state, step=step, steps=steps, text=text, user_id=user_id)
else:
if state.context['answer'] == 'да':
self.walking_through_scenario(state=state, step=step, steps=steps, text=text, user_id=user_id)
else:
next_step = step['failure_step']
state.delete()
self.send_step(step=step, user_id=user_id, text=text, context={})
UserState(user_id=str(user_id), scenario_name=state.scenario_name, step_name=next_step, context={})
else:
# retry_current_step
text_to_send = step['failure_text'].format(**state.context)
self.send_text(text_to_send=text_to_send, user_id=user_id)
# движения по сценарию
def walking_through_scenario(self, state, step, steps, text, user_id):
next_step = steps[step['next_step']]
self.send_step(step=next_step, user_id=user_id, text=text, context=state.context)
if next_step['next_step']:
# switch to next step
state.step_name = step['next_step']
else:
# finish scenario and delete user states
log.info(
'Зарегистрирован пользователь ФИО {name} следует из {city_from} в {city_to} телефон для контактов {phone} '.format(
**state.context))
Registration(name=state.context['name'], city_from=state.context['city_from'],
city_to=state.context['city_to'],
phone=state.context['phone'])
state.delete()
if __name__ == '__main__':
configure_logging()
bot = Bot(group_id=settings.GROUP_ID, token=settings.TOKEN)
bot.run()
it helped me this command Routes.select(lambda p: p.id > 0 ).delete(bulk=True)

Tidying up series of try... except statements?

I've written a script to pipe through data from the Kustomer API to our database, and although it works fine its a bit messy, was wondering if there's a more elegant solution to this. I'm defining the row of results im pushing through as a dictionary then pushing to MySQL, but the messy part comes when some of these values aren't available in the JSON all the time.
This has resulted in a try / except statements for each data point that may or may not be missing.
Is there a better way of doing this? Code below.
try:
record_data = {
'id': record['id'],
'created_at': str(datetime.strptime(record['attributes']['createdAt'], '%Y-%m-%dT%H:%M:%S.%fZ'))[:-7],
'last_activity_at': str(datetime.strptime(record['attributes']['lastActivityAt'], '%Y-%m-%dT%H:%M:%S.%fZ'))[:-7],
'first_marked_done': None,
'last_marked_done': None,
'assigned_team': record['attributes']['assignedTeams'][0] if record['attributes']['assignedTeams'] != [] else None,
'conversation_type': None,
'conversation_category': None,
'conversation_subcategory': None,
'message_count': record['attributes']['messageCount'],
'note_count': record['attributes']['noteCount'],
'satisfaction': record['attributes']['satisfaction'],
'status': None,
'email': 1 if len(list(filter(lambda x: x == 'email', record['attributes']['channels']))) > 0 else 0,
'chat': 1 if len(list(filter(lambda x: x == 'chat', record['attributes']['channels']))) > 0 else 0,
'priority': record['attributes']['priority'],
'direction': 'outbound' if record['attributes']['direction'] == 'out' else 'in',
'nlp_score': None,
'nlp_sentiment': None,
'waiting_for': None,
'sla_breach': None,
'sla_status': None,
'breached_sla': None,
'breached_at': None
}
try:
record_data['status'] = record['attributes']['status']
except KeyError:
pass
try:
record_data['conversation_type'] = record['attributes']['custom']['typeStr']
record_data['conversation_category'] = str(record['attributes']['custom']['categoryTree']).split('.')[0]
record_data['conversation_subcategory'] = str(record['attributes']['custom']['categoryTree']).split('.')[1] if len(str(record['attributes']['custom']['categoryTree']).split('.')) > 1 else None
except KeyError:
pass
try:
record_data['waiting_for'] = record['attributes']['custom']['typeStr']
except KeyError:
pass
try:
record_data['first_marked_done'] = str(datetime.strptime(record['attributes']['firstDone']['createdAt'], '%Y-%m-%dT%H:%M:%S.%fZ'))[:-7]
record_data['last_marked_done'] = str(datetime.strptime(record['attributes']['lastDone']['createdAt'], '%Y-%m-%dT%H:%M:%S.%fZ'))[:-7]
except KeyError:
pass
try:
record_data['sla_breach'] = 0 if record['attributes']['sla']['breached'] is False else 1
record_data['sla_status'] = record['attributes']['sla']['status']
if record_data['sla_breach'] == 1:
try:
record_data['breached_sla'] = record['attributes']['sla']['breach']['metric']
record_data['breached_at'] = record['attributes']['sla']['breach']['at']
except KeyError:
for m in record['attributes']['sla']['metrics']:
try:
if record['attributes']['sla']['metrics'][m]['breachAt'] == record['attributes']['sla']['summary']['firstBreachAt']:
record_data['breached_sla'] = m
record_data['breached_at'] = str(datetime.strptime(record['attributes']['sla']['summary']['firstBreachAt'], '%Y-%m-%dT%H:%M:%S.%fZ'))[:-7]
except KeyError:
pass
except KeyError:
record_data['sla_breach'] = 0
print(record_data)
self.db.insert_update(KustomerConversations(**record_data))
except KeyError:
pass
First you should try, where possible, to use dict.get with a default value specified. Next you can consider contextmanager to make your code significantly cleaner. Consider this:
try:
record_data['status'] = record['attributes']['status']
except KeyError:
pass
try:
record_data['conversation_type'] = record['attributes']['custom']['typeStr']
except KeyError:
pass
try:
record_data['waiting_for'] = record['attributes']['custom']['typeStr']
except KeyError:
pass
try:
record_data['first_marked_done'] = record['attributes']['firstDone']['createdAt']
except KeyError:
pass
Now rewritten, you can ensure consistent error handling without repeating logic:
from contextlib import contextmanager
#contextmanager
def error_handling():
try:
yield
except KeyError:
pass
with error_handling():
record_data['status'] = record['attributes']['status']
with error_handling():
record_data['conversation_type'] = record['attributes']['custom']['typeStr']
with error_handling():
record_data['waiting_for'] = record['attributes']['custom']['typeStr']
with error_handling():
record_data['first_marked_done'] = record['attributes']['firstDone']['createdAt']
You can define an arbitrary number of functions like error_handling for various rules you wish to apply.
You can use function, that give you element from nested dicts, and doesn't raise an exception, if it doesnt' exists.
Like this quick draft:
def get_nested_dict_value(src_dict, *nested_keys, **kwargs):
"""
Get value of some nested dict by series of keys with default value.
Example:
instead of:
x = data['a']['b']['c']['d']
use
x = get_nested_dict_value(data, 'a', 'b', 'c', 'd')
or, if you need some non-None default value, add default=xxx kwarg:
x = get_nested_dict_value(data, 'a', 'b', 'c', 'd', default=0)
"""
default = kwargs.get("default", None)
pointer = src_dict
i = 0
for key in nested_keys:
i += 1
if key in pointer:
pointer = pointer[key]
if i == len(nested_keys):
return pointer
else:
return default
So, instead of:
try:
record_data['conversation_type'] = record['attributes']['custom']['typeStr']
except Exception:
pass
You just type:
record_data['conversation_type'] = get_nested_dict_value(record, 'attributes', 'custom', 'typeStr')
The different naming conventions on the input and output sides make it hard to beat the clarity of explicit assignments. Preserving the exact semantics of your version (e.g., that it doesn't assign conversation_category in the absence of a typeStr even if categoryTree is available) excludes certain choices (like making a data structure to loop over with a try/except on each access); you might be able to do better with more assumptions about your input data.
Nonetheless, in addition to the dict.get already mentioned, you can use builtins (any, or, and dict) and introduce a helper function and a few temporary variables to make the code much more readable:
# this gives one digit of the hour for me...?
def ptime(s): return str(datetime.strptime(s,'%Y-%m-%dT%H:%M:%S.%fZ'))[:-7]
try:
attr=record['attributes']
cust=attr.get('custom',{}) # defer KeyErrors into the below
record_data = dict(
id = record['id'],
created_at = ptime(attr['createdAt']),
last_activity_at = ptime(attr['lastActivityAt']),
first_marked_done = None,
last_marked_done = None,
assigned_team = attr['assignedTeams'][0] or None,
conversation_type = None,
conversation_category = None,
conversation_subcategory = None,
message_count = attr['messageCount'],
note_count = attr['noteCount'],
satisfaction = attr['satisfaction'],
status = attr.get('status'),
email = int(any(x == 'email' for x in attr['channels'])),
chat = int(any(x == 'chat' for x in attr['channels'])),
priority = attr['priority'],
direction = 'outbound' if attr['direction'] == 'out' else 'in',
nlp_score = None,
nlp_sentiment = None,
waiting_for = cust.get('typeStr'),
sla_breach = 0,
sla_status = None,
breached_sla = None,
breached_at = None
)
try:
record_data['conversation_type'] = cust['typeStr']
cat=str(cust['categoryTree']).split('.')
record_data['conversation_category'] = cat[0]
record_data['conversation_subcategory'] = cat[1] if len(cat) > 1 else None
except KeyError: pass
try:
record_data['first_marked_done'] = ptime(attr['firstDone']['createdAt'])
record_data['last_marked_done'] = ptime(attr['lastDone']['createdAt'])
except KeyError: pass
try:
sla=attr['sla']
record_data['sla_breach'] = 0 if sla['breached'] is False else 1
record_data['sla_status'] = sla['status']
if record_data['sla_breach'] == 1:
try:
record_data['breached_sla'] = sla['breach']['metric']
record_data['breached_at'] = sla['breach']['at']
except KeyError:
for m,v in sla['metrics'].items():
try:
v=v['breachAt']
if v == sla['summary']['firstBreachAt']:
record_data['breached_sla'] = m
record_data['breached_at'] = ptime(v)
except KeyError: pass
except KeyError: pass
print(record_data)
self.db.insert_update(KustomerConversations(**record_data))
except KeyError: pass
While you might have a policy against it, in this case I recommend writing the remaining except KeyError: pass clauses on one line each: it helps the visual bracketing of the tentative code.

python raise exception where there looks not exception?

I have a problem that:
when testing on flask there is not exception
after put online by gunicorn+gevent, they raise an exception at following code
-
try:
req_dict = request.args.to_dict()
req_desc = copy.copy(req_dict)
temp_card_pwd = str(req_desc['cardpwd'])
req_desc['cardpwd'] = temp_card_pwd.replace(temp_card_pwd[5:9], "****")
log.info('接收到一条请求信息(charge_in##) %s' % req_desc)
request_type = str(req_dict['command'])
charge_acct = str(req_dict['telephone'])
card_pwd = str(req_dict['cardpwd'])
res_dict = req_validate(request_type, card_pwd, charge_acct)
if res_dict['errcode'] == 0:
log.info('准备充值(charge_begin##)...%s '% req_desc)
time_start = time.time()
acct_charge = True
charge_res = charge(req_desc, card_pwd, charge_acct)
res_dict['body'] = charge_res
log.info('充值结果(charge_end##):请求:%s, 结果:%s 耗时:%s' % (req_desc, res_dict,
int((time.time() - time_start)*1000)))
else:
log.warning('返回异常请求结果(charge_out##):请求:%s 结果:%s' % (req_desc, res_dict))
except Exception as e:
if acct_charge:
code = 1007
msg = '充值异常!%s' % e
else:
code = 1006
msg = '传入参数错误! %s' % e
res_dict = {'errcode': code, 'msg': msg, 'body': None}
log.warning('返回异常请求结果(charge_exception##):请求参数异常!请核对后再发!%s' % res_dict)
the exception is
2017-08-04 06:47:50,441 yidongserver.py[line:49] WARNING: [channel_name:yidongApp] 返回异常请求结果(charge_exception##):请求参数异常!请核对后再发!{'errcode': 1006, 'msg': '传入参数错误', 'body': None}
2017-08-04 06:47:50,445 yidongserver.py[line:25] INFO: [channel_name:yidongApp] 接收到一条请求信息(charge_in##) {'request_id': 'HF111708041450260032', 'card_id': '17356104229493840', 'telephone': '152***94608', 'cardpwd': '42381****349361850', 'money': '100', 'callbackurl': '', 'command': 'charge', 'channel_id': 'LTAppRY'}
Although raise this exception, this charge request still SUCCESS in charge, and return ONCE
pls help to solve this warning exception! thanks!

Categories

Resources