mirror of
https://github.com/bcomsugi/Quickbooks-API.git
synced 2026-01-10 02:02:38 +07:00
savedata
This commit is contained in:
parent
a7a1c6528d
commit
118ceb824d
24
QBClasses.py
24
QBClasses.py
@ -387,7 +387,7 @@ class SalesOrderQuery(baseQBQuery):
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]={}
|
||||
### End Required Variable. can put ENUM list below this (eg: self.ENUM_GeneralSummaryReportQuery=[])
|
||||
|
||||
if 'TxnID' in kwargs and kwargs['TxnID']:
|
||||
if 'TxnID' in kwargs and kwargs['TxnID'] and len(kwargs['TxnID'])>0:
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["TxnID"]=kwargs['TxnID']
|
||||
elif 'RefNumber' in kwargs and kwargs['RefNumber']:
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["RefNumber"]=kwargs['RefNumber']
|
||||
@ -467,14 +467,11 @@ class InvoiceQuery(baseQBQuery):
|
||||
|
||||
if 'TxnID' in kwargs and kwargs['TxnID']:
|
||||
_txnIDs=makeAList(kwargs['TxnID'])
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["TxnID"]= _txnIDs
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["TxnID"]= makeAList(kwargs['TxnID'])
|
||||
elif 'RefNumber' in kwargs and kwargs['RefNumber']:
|
||||
_refNumbers=makeAList(kwargs['RefNumber'])
|
||||
# print(f'{_refNumbers=}')
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]['RefNumber']=_refNumbers
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]['RefNumber']=makeAList(kwargs['RefNumber'])
|
||||
elif 'RefNumberCaseSensitive' in kwargs and kwargs['RefNumberCaseSensitive']:
|
||||
_refNumbersCaseSensitive=makeAList(kwargs['RefNumberCaseSensitive'])
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["RefNumberCaseSensitive"]=_refNumbersCaseSensitive
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["RefNumberCaseSensitive"]=makeAList(kwargs['RefNumberCaseSensitive'])
|
||||
else:
|
||||
if 'MaxReturned' in kwargs:
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["MaxReturned"]=kwargs['MaxReturned']
|
||||
@ -486,18 +483,20 @@ class InvoiceQuery(baseQBQuery):
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["TxnDateRangeFilter"]={'DateMacro':kwargs['TxnDateRangeFilter_DateMacro']}
|
||||
|
||||
if 'EntityFilter_ListID' in kwargs:
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["EntityFilter"]={'ListID':kwargs['EntityFilter_ListID']}
|
||||
# self.QBDict[self.__class__.__name__ + "Rq"]["EntityFilter"]={'ListID':kwargs['EntityFilter_ListID']}
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]['EntityFilter']={'ListID':makeAList(kwargs['EntityFilter_ListID'])}
|
||||
elif 'EntityFilter_FullName' in kwargs:
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["EntityFilter"]={'FullName':kwargs['EntityFilter_FullName']}
|
||||
# self.QBDict[self.__class__.__name__ + "Rq"]["EntityFilter"]={'FullName':kwargs['EntityFilter_FullName']}
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]['EntityFilter']={'FullName':makeAList(kwargs['EntityFilter_FullName'])}
|
||||
elif 'EntityFilter_ListIDWithChildren' in kwargs:
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["EntityFilter"]={'ListIDWithChildren':kwargs['EntityFilter_ListIDWithChildren']}
|
||||
elif 'EntityFilter_FullNameWithChildren' in kwargs:
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["EntityFilter"]={'FullNameWithChildren':kwargs['EntityFilter_FullNameWithChildren']}
|
||||
|
||||
if 'AccountFilter_ListID' in kwargs:
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["AccountFilter"]={'ListID':kwargs['AccountFilter_ListID']}
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["AccountFilter"]={'ListID':makeAList(kwargs['AccountFilter_ListID'])}
|
||||
elif 'AccountFilter_FullName' in kwargs:
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["AccountFilter"]={'FullName':kwargs['AccountFilter_FullName']}
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["AccountFilter"]={'FullName':makeAList(kwargs['AccountFilter_FullName'])}
|
||||
elif 'AccountFilter_ListIDWithChildren' in kwargs:
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["AccountFilter"]={'ListIDWithChildren':kwargs['AccountFilter_ListIDWithChildren']}
|
||||
elif 'AccountFilter_FullNameWithChildren' in kwargs:
|
||||
@ -506,7 +505,8 @@ class InvoiceQuery(baseQBQuery):
|
||||
if 'RefNumberFilter_MatchCriterion' in kwargs and 'RefNumberFilter_RefNumber' in kwargs:
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["RefNumberFilter"]={'MatchCriterion':kwargs['RefNumberFilter_MatchCriterion', 'RefNumber':kwargs['RefNumberFilter_RefNumber']]}
|
||||
elif 'RefNumberRangeFilter_FromRefNumber' in kwargs or 'RefNumberRangeFilter_ToRefNumber' in kwargs: #if or then use {'key1':kwargs.get('key1',""), 'key2':kwargs.get('key2', "")}
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["RefNumberRangeFilter"]={'FromRefNumber':kwargs.get('RefNumberRangeFilter_FromRefNumber', ""), 'ToRefNumber':kwargs.get('RefNumberRangeFilter_ToRefNumber', "")}
|
||||
##### CAREFULL with the get() coz "" will get anything
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["RefNumberRangeFilter"]={'FromRefNumber':kwargs.get('RefNumberRangeFilter_FromRefNumber', ""), 'ToRefNumber':kwargs.get('RefNumberRangeFilter_ToRefNumber', "")}
|
||||
|
||||
if 'CurrencyFilter_ListID' in kwargs:
|
||||
self.QBDict[self.__class__.__name__ + "Rq"]["CurrencyFilter"]=kwargs['CurrencyFilter_ListID']
|
||||
|
||||
109
save_data.py
109
save_data.py
@ -1,6 +1,6 @@
|
||||
from QBClasses import SalesOrderQuery, InvoiceQuery, TransactionQuery
|
||||
from utils import timing, makeAList
|
||||
from pprint import pprint
|
||||
from utils import timing, makeAList, makeLinkedTxnList
|
||||
from pprint import pprint, PrettyPrinter
|
||||
# h1="17b2d5"
|
||||
# h2="17b2c1"
|
||||
# res = int(h2,16)-int(h1,16)
|
||||
@ -16,14 +16,113 @@ def main():
|
||||
"IsToBeEmailed", "ExternalGUID",
|
||||
"LinkedTxn", "InvoiceLineRet", "InvoiceLineGroupRet",
|
||||
]
|
||||
so_IncludeRetElements = ["TxnID", "TimeCreated", "TimeModified", "EditSequence", "TxnNumber", "CustomerRef",
|
||||
"TxnDate", "RefNumber", "PONumber,", "SalesRepRef", "SubTotal", "TotalAmount",
|
||||
"IsManuallyClosed", "IsFullyInvoiced", "Memo", "CustomerMsgRef", "LinkedTxn", "SalesOrderLineRet", "SalesOrderLineGroupRet",
|
||||
]
|
||||
refNumbers_listofdict= [{'RefNumber': '0099'}, {'RefNumber': '0100'}, {'RefNumber': '0103'}]
|
||||
refNumbers_list= makeAList(refNumbers_listofdict,dictvalue=True, listofdict=True)
|
||||
print(refNumbers_list)
|
||||
invQ = InvoiceQuery(**{'debug':False, 'MaxReturned':100, 'RefNumber':refNumbers_list, 'IncludeLineItems':'true', 'IncludeLinkedTxns':'true'})#, 'IncludeRetElements':IncludeRetElements})#, 'OwnerID':0} )
|
||||
# invQ = InvoiceQuery(**{'debug':False, 'MaxReturned':1, 'RefNumber':refNumbers_list, 'IncludeLineItems':'true', 'IncludeLinkedTxns':'true', 'IncludeRetElements':IncludeRetElements})#, 'OwnerID':0} )
|
||||
invQ = InvoiceQuery(**{'debug':False, 'MaxReturned':1, 'IncludeLineItems':'true', 'IncludeLinkedTxns':'true', 'IncludeRetElement':IncludeRetElements})#, 'OwnerID':0} )
|
||||
|
||||
# print(pprint(invQ), type(invQ), pprint(invQ.all()))
|
||||
# print(invQ.response_string)
|
||||
print(invQ.filter("RefNumber"))
|
||||
print(invQ.count())
|
||||
# print(invQ.filter(["RefNumber","txnid"]))
|
||||
# print(invQ.all(), type(invQ.all()))
|
||||
# PrettyPrinter( sort_dicts=False).pprint(invQ.all())
|
||||
# pprint(invQ.all(),sort_dicts=False)
|
||||
print(f'{invQ.count() =}')
|
||||
|
||||
## start process ##
|
||||
invdicts = invQ.all()
|
||||
if isinstance(invdicts,dict):
|
||||
invdicts=[invdicts]
|
||||
|
||||
print("SALES ORDER")
|
||||
|
||||
for inv_idx, invdict in enumerate(invdicts): #loop over every Invoice, and get the linkedtxnID
|
||||
InvoiceLineRet = invQ.filter("InvoiceLineRet").all(invdict)
|
||||
linkedtxns = invQ.filter("LinkedTxn").all(invdict)
|
||||
print(f'{InvoiceLineRet=}', type(InvoiceLineRet))
|
||||
# print(linkedtxns, type(linkedtxns))
|
||||
linkedTxnIDs=makeLinkedTxnList(linkedtxns, 'SalesOrder') #this is the list of linkedTxn.TxnID
|
||||
print(f'{inv_idx=} of {len(invdicts)}; {linkedTxnIDs = }')
|
||||
so_init={'IncludeLineItems':'true', 'IncludeLinkedTxns':'true', 'TxnID':linkedTxnIDs, 'IncludeRetElement': so_IncludeRetElements}
|
||||
SOOrders=SalesOrderQuery(**so_init)
|
||||
# pprint(SOOrders.all(), sort_dicts=False)
|
||||
solineret = SOOrders.filter(["TxnID", "RefNumber", "SalesOrderLineRet"]).all()
|
||||
# print(solineret)
|
||||
sorefnumbers = SOOrders.filter("RefNumber").getValuesOf("RefNumber")
|
||||
print(f'{sorefnumbers=}')
|
||||
is_soRefNumber_duplicated = False
|
||||
for sorefNumber in sorefnumbers: #check if SO RefNumber is duplicated, not valid RefNumber raise error
|
||||
|
||||
checkduplicateRefNumber = SalesOrderQuery(RefNumber=sorefNumber)
|
||||
if checkduplicateRefNumber.count()==1:
|
||||
pass # SOrefnumber no duplicate
|
||||
print("no duplicate refnumber")
|
||||
|
||||
elif checkduplicateRefNumber.count()>1:
|
||||
is_soRefNumber_duplicated=True
|
||||
print(f"there is duplicate in one of there refnumbers:{sorefNumber=}")
|
||||
raise Exception(f"there is duplicate in one of there refnumbers:{sorefNumber=}")
|
||||
break
|
||||
print(f'{checkduplicateRefNumber.count() = }')
|
||||
if is_soRefNumber_duplicated:
|
||||
return
|
||||
|
||||
#prepare SOOrders to be a list of dict
|
||||
soorders = SOOrders.all()
|
||||
if isinstance(soorders, dict):
|
||||
soorders=[soorders]
|
||||
#start comparing inv to so line by line
|
||||
invLineRets = InvoiceLineRet[0].get('InvoiceLineRet')
|
||||
for invLineRet in invLineRets:
|
||||
FullName_inv = invLineRet['ItemRef']['FullName']
|
||||
TxnLineID_inv = invLineRet['TxnLineID']
|
||||
Quantity_inv = invLineRet['Quantity']
|
||||
UnitOfMeasure_inv = invLineRet['UnitOfMeasure']
|
||||
OverrideUOMSetRef_inv = invLineRet['OverrideUOMSetRef']['FullName']
|
||||
Rate_inv = invLineRet['Rate']
|
||||
Amount_inv = invLineRet['Amount']
|
||||
|
||||
for soorder in soorders:
|
||||
pass
|
||||
TxnID_so = soorder['TxnID']
|
||||
RefNumber_so = soorder['RefNumber']
|
||||
IsFullyInvoiced_so = soorder['IsFullyInvoiced']
|
||||
IsManuallyClosed_so = soorder['IsManuallyClosed']
|
||||
SalesOrderLineRet_so = soorder['SalesOrderLineRet']
|
||||
LinkedTxn_so = soorder['LinkedTxn']
|
||||
#prepare SalesOrderLineRet to be a list of dict
|
||||
if isinstance(SalesOrderLineRet_so, dict):
|
||||
SalesOrderLineRet_so = [SalesOrderLineRet_so]
|
||||
# print(f'{SalesOrderLineRet_so = }')
|
||||
for soLineRet_idx, soLineRet in enumerate(SalesOrderLineRet_so):
|
||||
# print(soLineRet_idx, soLineRet)
|
||||
print(f"{soLineRet_idx} {soLineRet.get('checked', False) = }")
|
||||
if soLineRet.get('checked', False): # if can find checked key and not True, then skip next soLineRet
|
||||
# print(soLineRet_idx,"continue")
|
||||
continue
|
||||
print(f'{soLineRet_idx = }->{soLineRet}')
|
||||
FullName_so = soLineRet['ItemRef']['FullName']
|
||||
TxnLineID_so = soLineRet['TxnLineID']
|
||||
Quantity_so = soLineRet['Quantity']
|
||||
UnitOfMeasure_so = soLineRet['UnitOfMeasure']
|
||||
OverrideUOMSetRef_so = soLineRet['OverrideUOMSetRef']['FullName']
|
||||
Rate_so = soLineRet['Rate']
|
||||
Amount_so = soLineRet['Amount']
|
||||
Invoiced_so = soLineRet.get('Invoiced',0)
|
||||
IsManuallyClosed_so = soLineRet['IsManuallyClosed']
|
||||
SalesOrderLineRet_so[soLineRet_idx]['checked']=True
|
||||
# break only if match with invlineret==solineret
|
||||
# pprint(solineret, sort_dicts=False)
|
||||
# pprint(SOOrders.all(), sort_dicts=False)
|
||||
# pprint(invQ.all())
|
||||
print(f'{SOOrders.count() = }')
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
|
||||
@ -69,7 +69,7 @@ class baseQBQuery:
|
||||
dataDict["?qbxml"]["QBXML"] = {"QBXMLMsgsRq": { ### Example with multiple FullName Item ###
|
||||
"@onError": self.onError,
|
||||
firstKey: self.QBDict[firstKey]}}
|
||||
print(f'{dataDict = }')
|
||||
# print(f'{dataDict = }')
|
||||
# # QBXML = '<?qbxml version="13.0"?>' + xmltodict.unparse(dataDict, pretty=True)
|
||||
self.QBXML = xmltodict.unparse(dataDict, pretty=True).replace("</?qbxml>", "").replace(f'version="{version}"', f'version="{version}"?')
|
||||
print(self.QBXML, type(self.QBXML))
|
||||
|
||||
19
utils.py
19
utils.py
@ -2,6 +2,25 @@
|
||||
from time import time
|
||||
from typing import Union
|
||||
|
||||
|
||||
def makeLinkedTxnList(x:list, key:str=None)->list:
|
||||
txnIDs=[]
|
||||
if isinstance(x, dict):
|
||||
x=[x]
|
||||
print(f'{type(x)=}')
|
||||
for y in x: #y = each dict of LinkedTxn, and it has a listofdict or a dict inside
|
||||
linkedTxns=y.get('LinkedTxn',None)
|
||||
if linkedTxns is None:
|
||||
return
|
||||
if isinstance(linkedTxns, dict):
|
||||
linkedTxns = [linkedTxns]
|
||||
for linkedTxn in linkedTxns:
|
||||
# print(f'{key = }')
|
||||
if key and linkedTxn.get('TxnType')==key:
|
||||
txnIDs.append(linkedTxn.get('TxnID',None))
|
||||
print(f'{txnIDs = }')
|
||||
return txnIDs
|
||||
|
||||
def makeAList(x:Union[str , dict , list], dictvalue:bool=False, listofdict:bool=False)->list :
|
||||
if isinstance(x,str):
|
||||
x=[x]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user