update exim

This commit is contained in:
bcomsugi 2025-02-21 06:08:34 +07:00
parent 89982de5b0
commit c8c7816f01

130
exim.py
View File

@ -6,6 +6,8 @@ from QBClass.QBClasses import InvoiceQuery, SalesOrderQuery
import time import time
import json import json
import pandas as pd import pandas as pd
import numpy as np
import datetime
print('succes Loading modules') print('succes Loading modules')
@ -26,7 +28,7 @@ def timer(func):
@timer @timer
def get_all_so_from_invoice(MaxReturned=None, FromTxnDate=None, ToTxnDate=None): def get_all_so_from_invoice( FromTxnDate=None, ToTxnDate=None, MaxReturned=None,):
print(MaxReturned, FromTxnDate, ToTxnDate) print(MaxReturned, FromTxnDate, ToTxnDate)
start = time.time() start = time.time()
print('Get Invoice Query List. Processing..... wait for at minute(1 month=90secs)') print('Get Invoice Query List. Processing..... wait for at minute(1 month=90secs)')
@ -160,6 +162,7 @@ def process():
@timer @timer
def process_data(iq_list, so_dict): def process_data(iq_list, so_dict):
print('process_data')
# iq = InvoiceQuery(MaxReturned= 20, IncludeLinkedTxns='true', IncludeLineItems='true', debug=False) # iq = InvoiceQuery(MaxReturned= 20, IncludeLinkedTxns='true', IncludeLineItems='true', debug=False)
# iq = InvoiceQuery(TxnDateRangeFilter_FromTxnDate='2024-02-01', TxnDateRangeFilter_ToTxnDate='2024-02-29', IncludeLinkedTxns='true', IncludeLineItems='true') # iq = InvoiceQuery(TxnDateRangeFilter_FromTxnDate='2024-02-01', TxnDateRangeFilter_ToTxnDate='2024-02-29', IncludeLinkedTxns='true', IncludeLineItems='true')
# pprint(iq_list, sort_dicts=False) # pprint(iq_list, sort_dicts=False)
@ -214,19 +217,20 @@ def process_data(iq_list, so_dict):
soNotInOneInv.append(sodt['RefNumber']) soNotInOneInv.append(sodt['RefNumber'])
if float(linkedtxn['Amount'])<0: if float(linkedtxn['Amount'])<0:
if sodt['TotalAmount']!=linkedtxn['Amount'][1:]: # if sodt['TotalAmount']!=linkedtxn['Amount'][1:]:
if is_soLinkedToOneInvoice: #maybe the SO is manually closed, check it item by item, find which item is not in invoice # pass
if sodt['IsManuallyClosed'] == 'true': # if is_soLinkedToOneInvoice: #maybe the SO is manually closed, check it item by item, find which item is not in invoice
pass # if sodt['IsManuallyClosed'] == 'true':
print(f"{sodt['TxnID'] = } {sodt['RefNumber'] = }") # pass
manuallyClosedSO.append(sodt['RefNumber']) # print(f"{sodt['TxnID'] = } {sodt['RefNumber'] = }")
else: # manuallyClosedSO.append(sodt['RefNumber'])
print('SO TotalAmount<>Amount in Invoice. not Manually closed and not fully Invoiced') # else:
pprint(f'{linkedtxn = }', sort_dicts=False) # print('SO TotalAmount<>Amount in Invoice. not Manually closed and not fully Invoiced')
print(f"{sodt['TxnID'] = } {sodt['RefNumber'] = }") # pprint(f'{linkedtxn = }', sort_dicts=False)
print(sodt) # print(f"{sodt['TxnID'] = } {sodt['RefNumber'] = }")
openSO.append(sodt['RefNumber']) # print(sodt)
else: # openSO.append(sodt['RefNumber'])
# else:
pass # this SO is fully invoiced, starting process to export the details pass # this SO is fully invoiced, starting process to export the details
try: try:
if not isinstance(sodt['SalesOrderLineRet'],list): if not isinstance(sodt['SalesOrderLineRet'],list):
@ -252,7 +256,7 @@ def process_data(iq_list, so_dict):
for inv_line in txn['InvoiceLineRet']: #loop start from top in order for inv_line in txn['InvoiceLineRet']: #loop start from top in order
is_inv_so_line_ok = True is_inv_so_line_ok = True
if 'soline' not in inv_line: #this line has no so link yet if 'soline' not in inv_line: #this line has no so link yet
if inv_line['ItemRef']['FullName'] != soitemref_fullname: if inv_line.get('ItemRef',{}).get('FullName') != soitemref_fullname:
continue continue
if inv_line.get('UnitOfMeasure') != sounitofmeasure: if inv_line.get('UnitOfMeasure') != sounitofmeasure:
print(f"{inv_line['ItemRef']['FullName'] = } {inv_line['UnitOfMeasure']=} != {sounitofmeasure=}") print(f"{inv_line['ItemRef']['FullName'] = } {inv_line['UnitOfMeasure']=} != {sounitofmeasure=}")
@ -266,11 +270,10 @@ def process_data(iq_list, so_dict):
if float(inv_line.get('Rate',0))!=float(sorate): if float(inv_line.get('Rate',0))!=float(sorate):
print(f"{inv_line['ItemRef']['FullName'] = } {inv_line['Rate']=} <> {sorate=} ; {float(inv_line.get('Rate',0)) = } {float(sorate) = }") print(f"{inv_line['ItemRef']['FullName'] = } {inv_line['Rate']=} <> {sorate=} ; {float(inv_line.get('Rate',0)) = } {float(sorate) = }")
is_inv_so_line_ok = False is_inv_so_line_ok = False
# if inv_line['Amount']!=soamount or float(inv_line['Amount'])!=float(soamount): # if soamount:
if soamount: # if float(inv_line.get('Amount',0))!=float(soamount):
if float(inv_line.get('Amount',0))!=float(soamount): # print(f"{txn['RefNumber']} {inv_line['ItemRef']['FullName'] = } {inv_line['Amount']=} != {soamount=}")
print(f"{inv_line['ItemRef']['FullName'] = } {inv_line['Amount']=} != {soamount=}") # is_inv_so_line_ok = False
is_inv_so_line_ok = False
if not is_inv_so_line_ok: if not is_inv_so_line_ok:
print(f"{inv_line['ItemRef']['FullName'] = } Some detail not equal") print(f"{inv_line['ItemRef']['FullName'] = } Some detail not equal")
continue continue
@ -329,9 +332,7 @@ def checking_iqwith_so(iq_list):
continue continue
if 'ItemRef' not in inv_line: if 'ItemRef' not in inv_line:
inv_line_no_itemref.append({'RefNumber':txn['RefNumber'], inv_line_no_itemref.append({'RefNumber':txn['RefNumber'],
'idx':idx, 'idx':idx,})
'ItemRef_FullName':inv_line['ItemRef']['FullName'],
'Amount':inv_line['Amount']})
continue continue
if '400_Sales' not in inv_line['ItemRef']['FullName']: if '400_Sales' not in inv_line['ItemRef']['FullName']:
inv_line_no_soline.append({'RefNumber':txn['RefNumber'], inv_line_no_soline.append({'RefNumber':txn['RefNumber'],
@ -364,7 +365,7 @@ def writeToFile(iq_list=None, so_dict=None, filename = "", suffix="", indent=2):
so_dict_json = json.dumps(so_dict) so_dict_json = json.dumps(so_dict)
else: else:
so_dict_json = json.dumps(so_dict, indent=indent) so_dict_json = json.dumps(so_dict, indent=indent)
with open(f"{filename}{suffix}.json", "w") as outfile: with open(f"{filename}_so_dict{suffix}.json", "w") as outfile:
outfile.write(so_dict_json) outfile.write(so_dict_json)
return True return True
except Exception as e: except Exception as e:
@ -380,24 +381,71 @@ def readJsonFromFile(filename):
print(e) print(e)
return [] return []
# print(timeit.repeat(process, repeat=1))
# process()
invqueryfilename = 'exim\Data\iq' def get_last_date_of_month(stryearmonth:str):
# iq_list, so_dict = get_all_so_from_invoice(MaxReturned=20) # Get Last date of Month
### Reading from QB and write to a file depends on txndate # Using replace() + timedelta()
# iq_list, so_dict = get_all_so_from_invoice(FromTxnDate="2024-08-01", ToTxnDate="2024-08-31")
# writeToFile(iq_list, so_dict)
### reading from existing file the iq_list and so_dict jsonfile # initializing date
test_date = datetime.datetime.fromisoformat(stryearmonth)
# test_date = datetime.datetime(2018, 6, 4)
iq_list = readJsonFromFile(f"{invqueryfilename}.json") # printing original date
so_dict = readJsonFromFile(f"{invqueryfilename}_so_dict.json") print("The original date is : " + str(test_date))
print(f'{len(iq_list) = } {len(so_dict) = }')
iq_list = process_data(iq_list, so_dict)
suffix = '_withsoindent2'
writeToFile(iq_list, filename=f'{invqueryfilename}', suffix=suffix, indent=2)
iq_list = readJsonFromFile(f'{invqueryfilename}{suffix}.json')
print(len(iq_list))
print(f'Seems {invqueryfilename}{suffix}.json is {checking_iqwith_so(iq_list)}') #checking the iq_list. is it good to import to new QB?
# getting next month
# using replace to get to last day + offset
# to reach next month
nxt_mnth = test_date.replace(day=28) + datetime.timedelta(days=4)
# subtracting the days from next month date to
# get last date of current Month
res = nxt_mnth - datetime.timedelta(days=nxt_mnth.day)
# printing result
datesplit = stryearmonth.split('-')
print("Last date of month : " + str(res.day), f"{datesplit[0]}-{datesplit[1]}-{str(res.day)}")
return f"{datesplit[0]}-{datesplit[1]}-{str(res.day)}"
def main(fromtxndate, totxndate, maxreturned:int=None):
# print(timeit.repeat(process, repeat=1))
# process()
invqueryfilename = f'exim\Data\{fromtxndate}iq'
# if maxreturned:
# iq_list, so_dict = get_all_so_from_invoice(MaxReturned=maxreturned)
# else:
# try:
# _fromdate = datetime.datetime.fromisoformat(fromtxndate)
# _todate = datetime.datetime.fromisoformat(totxndate)
# except Exception as e:
# print('date format should be yyyy-mm-dd example: "2024-03-09"')
# return False
# ## Reading from QB and write to a file depends on txndate
# iq_list, so_dict = get_all_so_from_invoice(FromTxnDate=fromtxndate, ToTxnDate=totxndate)
# writeToFile(iq_list, so_dict, filename=invqueryfilename)
### reading from existing file the iq_list and so_dict jsonfile
iq_list = readJsonFromFile(f"{invqueryfilename}.json")
so_dict = readJsonFromFile(f"{invqueryfilename}_so_dict.json")
print(f'{len(iq_list) = } {len(so_dict) = }')
iq_list = process_data(iq_list, so_dict)
suffix = '_withsoindent2'
writeToFile(iq_list, filename=f'{invqueryfilename}', suffix=suffix, indent=2)
iq_list = readJsonFromFile(f'{invqueryfilename}{suffix}.json')
print(len(iq_list))
print(f'Seems {invqueryfilename}{suffix}.json is {checking_iqwith_so(iq_list)}') #checking the iq_list. is it good to import to new QB?
if __name__=='__main__':
# print(np.arange('2021-02', '2021-03', dtype='datetime64[D]'))
fromtxndate = '2022-08-01'
totxndate = get_last_date_of_month(fromtxndate)
_fromdate = datetime.datetime.fromisoformat(fromtxndate)
print(fromtxndate)
main(fromtxndate, totxndate)