diff --git a/QBClasses.py b/QBClasses.py index 0db130b..ad97cc5 100644 --- a/QBClasses.py +++ b/QBClasses.py @@ -2,7 +2,7 @@ from server import baseQBQuery, timing import pprint import timeit import xml.dom.minidom -from utils import timing, cleanIncludeRetElements +from utils import timing, cleanIncludeRetElements, makeAList import json # from functools import wraps @@ -374,7 +374,7 @@ class SalesOrderQuery(baseQBQuery): ### Required Variable self.includeRetElements_allowed = ["TxnID", "TimeCreated", "TimeModified", "EditSequence", "TxnNumber", "CustomerRef", "ClassRef", "TemplateRef", "TxnDate", "RefNumber", "BillAddress", "BillAddressBlock", "ShipAddress", "ShipAddressBlock", "PONumber,", "TermsRef", "DueDate", - "SalesRefRef", "FOB", "ShipDate", "ShipMethodRef", "SubTotal", "ItemSalesTaxRef", "SalesTaxPercentage", "SalesTaxTotal", "TotalAmount", + "SalesRepRef", "FOB", "ShipDate", "ShipMethodRef", "SubTotal", "ItemSalesTaxRef", "SalesTaxPercentage", "SalesTaxTotal", "TotalAmount", "CurrencyRef", "ExchangeRate", "TotalAmountInHomeCurrency", "IsManuallyClosed", "IsFullyInvoiced", "Memo", "CustomerMsgRef", "IsToBePrinted", "IsToBeEmailed", "IsTaxIncluded", "CustomerSalesTaxCodeRef", "Other", "ExternalGUID", "LinkedTxn", "SalesOrderLineRet", "SalesOrderLineGroupRet" ] @@ -387,11 +387,11 @@ 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: + if 'TxnID' in kwargs and kwargs['TxnID']: self.QBDict[self.__class__.__name__ + "Rq"]["TxnID"]=kwargs['TxnID'] - elif 'RefNumber' in kwargs: + elif 'RefNumber' in kwargs and kwargs['RefNumber']: self.QBDict[self.__class__.__name__ + "Rq"]["RefNumber"]=kwargs['RefNumber'] - elif 'RefNumberCaseSensitive' in kwargs: + elif 'RefNumberCaseSensitive' in kwargs and kwargs['RefNumberCaseSensitive']: self.QBDict[self.__class__.__name__ + "Rq"]["RefNumberCaseSensitive"]=kwargs['RefNumberCaseSensitive'] else: if 'MaxReturned' in kwargs: @@ -442,12 +442,113 @@ class SalesOrderQuery(baseQBQuery): self.runCheck() ### running the qbxml connection to get data ### +class InvoiceQuery(baseQBQuery): + def __init__(self, *args, **kwargs): + + print(f'{args = }') + print(f'{kwargs = }') + super().__init__(*args, **kwargs) + ### Required Variable + self.includeRetElements_allowed = ["TxnID", "TimeCreated", "TimeModified", "EditSequence", "TxnNumber", "CustomerRef", "ClassRef", "ARAccountRef", "TemplateRef", + "TxnDate", "RefNumber", "BillAddress", "BillAddressBlock", "ShipAddress", "ShipAddressBlock", "IsPending", "IsFinanceCharge", "PONumber,", "TermsRef", "DueDate", + "SalesRepRef", "FOB", "ShipDate", "ShipMethodRef", "SubTotal", "ItemSalesTaxRef", "SalesTaxPercentage", "SalesTaxTotal", "AppliedAmount", "BalanceRemaining", + "CurrencyRef", "ExchangeRate", "BalanceRemainingInHomeCurrency", "Memo", "IsPaid", "CustomerMsgRef", "IsToBePrinted", + "IsToBeEmailed", "IsTaxIncluded", "CustomerSalesTaxCodeRef", "SuggestedDiscountAmount", "SuggestedDiscountDate", "Other", "ExternalGUID", + "LinkedTxn", "InvoiceLineRet", "InvoiceLineGroupRet", + ] + self.onError = "stopOnError" + self.retName = 'InvoiceRet' + self.defaultFilterKey = "TxnID" + if 'debug' in kwargs and isinstance(kwargs['debug'], bool): + self.class_debug=kwargs["debug"] + + 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']: + _txnIDs=makeAList(kwargs['TxnID']) + self.QBDict[self.__class__.__name__ + "Rq"]["TxnID"]= _txnIDs + elif 'RefNumber' in kwargs and kwargs['RefNumber']: + _refNumbers=makeAList(kwargs['RefNumber']) + # print(f'{_refNumbers=}') + self.QBDict[self.__class__.__name__ + "Rq"]['RefNumber']=_refNumbers + elif 'RefNumberCaseSensitive' in kwargs and kwargs['RefNumberCaseSensitive']: + _refNumbersCaseSensitive=makeAList(kwargs['RefNumberCaseSensitive']) + self.QBDict[self.__class__.__name__ + "Rq"]["RefNumberCaseSensitive"]=_refNumbersCaseSensitive + else: + if 'MaxReturned' in kwargs: + self.QBDict[self.__class__.__name__ + "Rq"]["MaxReturned"]=kwargs['MaxReturned'] + if 'ModifiedDateRangeFilter_FromModifiedDate' in kwargs or 'ModifiedDateRangeFilter_ToModifiedDate' in kwargs: #if or then use {'key1':kwargs.get('key1',""), 'key2':kwargs.get('key2', "")} + self.QBDict[self.__class__.__name__ + "Rq"]["ModifiedDateRangeFilter"]={'FromModifiedDate':kwargs.get('ModifiedDateRangeFilter_FromModifiedDate', ""), 'ToModifiedDate':kwargs.get('ModifiedDateRangeFilter_ToModifiedDate', "")} + elif 'TxnDateRangeFilter_FromTxnDate' in kwargs or 'TxnDateRangeFilter_ToTxnDate' in kwargs: #if or then use {'key1':kwargs.get('key1',""), 'key2':kwargs.get('key2', "")} + self.QBDict[self.__class__.__name__ + "Rq"]["TxnDateRangeFilter"]={'FromTxnDate':kwargs.get('TxnDateRangeFilter_FromTxnDate', ""), 'ToTxnDate':kwargs.get('TxnDateRangeFilter_ToTxnDate', "")} + elif 'TxnDateRangeFilter_DateMacro' in kwargs: + 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']} + elif 'EntityFilter_FullName' in kwargs: + self.QBDict[self.__class__.__name__ + "Rq"]["EntityFilter"]={'FullName':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']} + elif 'AccountFilter_FullName' in kwargs: + self.QBDict[self.__class__.__name__ + "Rq"]["AccountFilter"]={'FullName':kwargs['AccountFilter_FullName']} + elif 'AccountFilter_ListIDWithChildren' in kwargs: + self.QBDict[self.__class__.__name__ + "Rq"]["AccountFilter"]={'ListIDWithChildren':kwargs['AccountFilter_ListIDWithChildren']} + elif 'AccountFilter_FullNameWithChildren' in kwargs: + self.QBDict[self.__class__.__name__ + "Rq"]["AccountFilter"]={'FullNameWithChildren':kwargs['AccountFilter_FullNameWithChildren']} + + 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', "")} + + if 'CurrencyFilter_ListID' in kwargs: + self.QBDict[self.__class__.__name__ + "Rq"]["CurrencyFilter"]=kwargs['CurrencyFilter_ListID'] + elif 'CurrencyFilter_FullName' in kwargs: + self.QBDict[self.__class__.__name__ + "Rq"]["CurrencyFilter"]=kwargs['CurrencyFilter_FullName'] + + if 'IncludeLineItems' in kwargs: + print(f'{self.QBDict} = ') + self.QBDict[self.__class__.__name__ + "Rq"]["IncludeLineItems"]=kwargs['IncludeLineItems'] + if 'IncludeLinkedTxns' in kwargs: + self.QBDict[self.__class__.__name__ + "Rq"]["IncludeLinkedTxns"]=kwargs['IncludeLinkedTxns'] + if 'IncludeRetElement' in kwargs: + IRE = cleanIncludeRetElements(self.includeRetElements_allowed, kwargs["IncludeRetElement"]) # IRE->IncludeRetElements cleaned version + print(f"{IRE = }") + if len(IRE)>0: + if self.defaultFilterKey not in IRE: # defaultFilterKey is for BaseClass.count() eg: after instantiate, then print obj.count() + IRE.append(self.defaultFilterKey) + self.QBDict[self.__class__.__name__ + "Rq"]["IncludeRetElement"]=IRE + + if 'OwnerID' in kwargs: # usually value=0 to get to DataExtRet (additional data) + self.QBDict[self.__class__.__name__ + "Rq"]["OwnerID"]=kwargs['OwnerID'] + + # print(self.__class__.__name__ + "Rq") + # print(self.QBDict) + self.runCheck() ### running the qbxml connection to get data ### + + if __name__ == "__main__": @timing - def salesorderquery(): - g=SalesOrderQuery(debug=False, MaxReturned = 2, EntityFilter_FullName="Abadi Serpong", TxnID="1786D5-1689047665", IncludeLineItems="true", IncludeLinkedTxns="true") + def invoicequery(): + g=InvoiceQuery(debug=False, MaxReturned = 2, IncludeLineItems="true", IncludeLinkedTxns="true", + RefNumber="24010022")#"2023-08-22") print(json.dumps(g.filter().all(), indent=3)) print(g.count()) + + @timing + def salesorderquery(): + g=SalesOrderQuery(debug=False, MaxReturned = None, TxnID=None, IncludeLineItems="true", IncludeLinkedTxns="true", + RefNumber="24010022" )#"B23070857") + print(json.dumps(g.filter().all(), indent=3)) + print(g.count()) + @timing def transactionquery(): g=TransactionQuery(debug=False, MaxReturned=None, TransactionTypeFilter_TxnTypeFilter="Invoice", TransactionEntityFilter_FullName="Abadi Serpong", @@ -562,7 +663,8 @@ if __name__ == "__main__": print(recursiveDict(varDict, f, enumDict)) f.close - salesorderquery() + invoicequery() + # salesorderquery() # transactionquery() # main() # iteminventoryquery() diff --git a/save_data.py b/save_data.py new file mode 100644 index 0000000..bed98ee --- /dev/null +++ b/save_data.py @@ -0,0 +1,30 @@ +from QBClasses import SalesOrderQuery, InvoiceQuery, TransactionQuery +from utils import timing, makeAList +from pprint import pprint +# h1="17b2d5" +# h2="17b2c1" +# res = int(h2,16)-int(h1,16) +# print(res, type(res), hex(res)[2:]) + +# print(h1list : + if isinstance(x,str): + x=[x] + elif isinstance(x, list) and not listofdict: #lists of str or int values + pass + elif isinstance(x, list) and not dictvalue: #lists of dict, and get all the keys + res=[] + for z in x: + for k in z: + res.append(k) + return res + elif isinstance(x, list) and dictvalue: #lists of dict, and get all the values + res=[] + for z in x: + for k,v in z.items(): + res.append(v) + return res + elif isinstance(x, list): #lists of str or int values + res=[] + for z in x: + for k in z: + res.append(k) + return res + elif isinstance(x, dict) and not dictvalue: #get a list of keys from dict + x=[k for k in x] + elif isinstance(x, dict): #get a list of values from dict + x=[v for k,v in x.items()] + + return x def timing(f): # @wraps(f) @@ -24,4 +54,10 @@ def cleanIncludeRetElements(includeRetElements_allowed:list, includeRetElements: if iRE.lower() == iRE_a.lower(): iREs.append(iRE_a) break - return iREs \ No newline at end of file + return iREs + +if __name__=='__main__': + #Example makelist + print(makeAList("hallo"), makeAList({'world':1, 'case':'another'}), makeAList(['here', 'we', 'go']), makeAList(1), makeAList({'world':1, 'case':'another'}, True)) + alistofdict = [{'RefNumber': '0001'}, {'RefNumber': '0022'}, {'RefNumber': '0004'}, {'RefNumber': '0006'}, {'RefNumber': '0008'}, {'RefNumber': '0009'}, {'RefNumber': '0010'}, {'RefNumber': '0015'}, {'RefNumber': '0065'}, {'RefNumber': '0017'}, {'RefNumber': '0019'}, {'RefNumber': '0023'}, {'RefNumber': '0024'}, {'RefNumber': '0025'}, {'RefNumber': '0027'}, {'RefNumber': '0029'}, {'RefNumber': '0030'}, {'RefNumber': '0045'}, {'RefNumber': '0032'}, {'RefNumber': '0034'}, {'RefNumber': '0035'}, {'RefNumber': '0036'}, {'RefNumber': '0040'}, {'RefNumber': '0003'}, {'RefNumber': '0031'}, {'RefNumber': '0033'}, {'RefNumber': '0037'}, {'RefNumber': '0038'}, {'RefNumber': '0039'}, {'RefNumber': '0047'}, {'RefNumber': '0005'}, {'RefNumber': '0007'}, {'RefNumber': '0012'}, {'RefNumber': '0013'}, {'RefNumber': '0014'}, {'RefNumber': '0016'}, {'RefNumber': '0011'}, {'RefNumber': '0021'}, {'RefNumber': '0002'}, {'RefNumber': '0018'}, {'RefNumber': '0020'}, {'RefNumber': '0026'}, {'RefNumber': '0028'}, {'RefNumber': '0041'}, {'RefNumber': '0051'}, {'RefNumber': '0062'}, {'RefNumber': '0042'}, {'RefNumber': '0043'}, {'RefNumber': '0053'}, {'RefNumber': '0055'}, {'RefNumber': '0057'}, {'RefNumber': '0058'}, {'RefNumber': '0059'}, {'RefNumber': '0061'}, {'RefNumber': '0068'}, {'RefNumber': '0044'}, {'RefNumber': '0046'}, {'RefNumber': '0048'}, {'RefNumber': '0049'}, {'RefNumber': '0050'}, {'RefNumber': '0086'}, {'RefNumber': '0054'}, {'RefNumber': '0056'}, {'RefNumber': '0060'}, {'RefNumber': '0052'}, {'RefNumber': '0064'}, {'RefNumber': '0066'}, {'RefNumber': '0070'}, {'RefNumber': '0071'}, {'RefNumber': '0072'}, {'RefNumber': '0075'}, {'RefNumber': '0076'}, {'RefNumber': '0078'}, {'RefNumber': '0080'}, {'RefNumber': '0081'}, {'RefNumber': '0085'}, {'RefNumber': '0067'}, {'RefNumber': '0069'}, {'RefNumber': '0073'}, {'RefNumber': '0074'}, {'RefNumber': '0077'}, {'RefNumber': '0079'}, {'RefNumber': '0082'}, {'RefNumber': '0083'}, {'RefNumber': '0084'}, {'RefNumber': '0087'}, {'RefNumber': '0089'}, {'RefNumber': '0091'}, {'RefNumber': '0092'}, {'RefNumber': '0093'}, {'RefNumber': '0094'}, {'RefNumber': '0095'}, {'RefNumber': '0096'}, {'RefNumber': '0167'}, {'RefNumber': '0088'}, {'RefNumber': '0097'}, {'RefNumber': '0098'}, {'RefNumber': '0099'}, {'RefNumber': '0100'}, {'RefNumber': '0103'}] + print(makeAList(alistofdict,listofdict=True, dictvalue=True)) \ No newline at end of file