This commit is contained in:
Sugiarto 2025-02-28 02:03:54 +07:00
commit cf7293c912
12 changed files with 3132 additions and 1747 deletions

1
.gitignore vendored
View File

@ -170,3 +170,4 @@ QBbackup/
.pdf
QBbackup/
test_folder_source_DeliveryNote/
Exim/Data

View File

@ -1,6 +1,6 @@
cd "C:\Sources\dasaproject\"
echo already cd
cmd /k "cd /d C:\Sources\dasaproject\env\Scripts\ & activate & cd /d C:\Sources\dasaproject\ & uvicorn main:app --host 0.0.0.0 --port 9997
cmd /k "cd /d C:\Sources\dasaproject\env\Scripts\ & activate & cd /d C:\Sources\dasaproject\ & uvicorn main:app --host 0.0.0.0 --port 9999
echo workon env
echo pause
echo get to env

0
Exim/__init__.py Normal file
View File

454
InvoiceAdd.xml Normal file
View File

@ -0,0 +1,454 @@
<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="16.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<InvoiceAddRq>
<InvoiceAdd defMacro="MACROTYPE"> <!-- required -->
<CustomerRef> <!-- required -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</CustomerRef>
<ClassRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ClassRef>
<ARAccountRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ARAccountRef>
<TemplateRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</TemplateRef>
<TxnDate >DATETYPE</TxnDate> <!-- optional -->
<RefNumber >STRTYPE</RefNumber> <!-- optional -->
<BillAddress> <!-- optional -->
<Addr1 >STRTYPE</Addr1> <!-- optional -->
<Addr2 >STRTYPE</Addr2> <!-- optional -->
<Addr3 >STRTYPE</Addr3> <!-- optional -->
<Addr4 >STRTYPE</Addr4> <!-- optional -->
<Addr5 >STRTYPE</Addr5> <!-- optional -->
<City >STRTYPE</City> <!-- optional -->
<State >STRTYPE</State> <!-- optional -->
<PostalCode >STRTYPE</PostalCode> <!-- optional -->
<Country >STRTYPE</Country> <!-- optional -->
<Note >STRTYPE</Note> <!-- optional -->
</BillAddress>
<ShipAddress> <!-- optional -->
<Addr1 >STRTYPE</Addr1> <!-- optional -->
<Addr2 >STRTYPE</Addr2> <!-- optional -->
<Addr3 >STRTYPE</Addr3> <!-- optional -->
<Addr4 >STRTYPE</Addr4> <!-- optional -->
<Addr5 >STRTYPE</Addr5> <!-- optional -->
<City >STRTYPE</City> <!-- optional -->
<State >STRTYPE</State> <!-- optional -->
<PostalCode >STRTYPE</PostalCode> <!-- optional -->
<Country >STRTYPE</Country> <!-- optional -->
<Note >STRTYPE</Note> <!-- optional -->
</ShipAddress>
<IsPending >BOOLTYPE</IsPending> <!-- optional -->
<IsFinanceCharge >BOOLTYPE</IsFinanceCharge> <!-- optional -->
<PONumber >STRTYPE</PONumber> <!-- optional -->
<TermsRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</TermsRef>
<DueDate >DATETYPE</DueDate> <!-- optional -->
<SalesRepRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</SalesRepRef>
<FOB >STRTYPE</FOB> <!-- optional -->
<ShipDate >DATETYPE</ShipDate> <!-- optional -->
<ShipMethodRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ShipMethodRef>
<ItemSalesTaxRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ItemSalesTaxRef>
<Memo >STRTYPE</Memo> <!-- optional -->
<CustomerMsgRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</CustomerMsgRef>
<IsToBePrinted >BOOLTYPE</IsToBePrinted> <!-- optional -->
<IsToBeEmailed >BOOLTYPE</IsToBeEmailed> <!-- optional -->
<IsTaxIncluded >BOOLTYPE</IsTaxIncluded> <!-- optional -->
<CustomerSalesTaxCodeRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</CustomerSalesTaxCodeRef>
<Other >STRTYPE</Other> <!-- optional -->
<ExchangeRate >FLOATTYPE</ExchangeRate> <!-- optional -->
<ExternalGUID >GUIDTYPE</ExternalGUID> <!-- optional -->
<LinkToTxnID >IDTYPE</LinkToTxnID> <!-- optional, may repeat -->
<SetCredit> <!-- optional, may repeat -->
<CreditTxnID useMacro="MACROTYPE">IDTYPE</CreditTxnID> <!-- required -->
<AppliedAmount >AMTTYPE</AppliedAmount> <!-- required -->
<Override >BOOLTYPE</Override> <!-- optional -->
</SetCredit>
<!-- BEGIN OR -->
<InvoiceLineAdd defMacro="MACROTYPE"> <!-- optional -->
<ItemRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ItemRef>
<Desc >STRTYPE</Desc> <!-- optional -->
<Quantity >QUANTYPE</Quantity> <!-- optional -->
<UnitOfMeasure >STRTYPE</UnitOfMeasure> <!-- optional -->
<!-- BEGIN OR -->
<Rate >PRICETYPE</Rate> <!-- optional -->
<!-- OR -->
<RatePercent >PERCENTTYPE</RatePercent> <!-- optional -->
<!-- OR -->
<PriceLevelRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</PriceLevelRef>
<!-- END OR -->
<ClassRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ClassRef>
<Amount >AMTTYPE</Amount> <!-- optional -->
<!-- OptionForPriceRuleConflict may have one of the following values: Zero, BasePrice -->
<OptionForPriceRuleConflict >ENUMTYPE</OptionForPriceRuleConflict> <!-- optional -->
<InventorySiteRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</InventorySiteRef>
<InventorySiteLocationRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</InventorySiteLocationRef>
<!-- BEGIN OR -->
<SerialNumber >STRTYPE</SerialNumber> <!-- optional -->
<!-- OR -->
<LotNumber >STRTYPE</LotNumber> <!-- optional -->
<!-- END OR -->
<ServiceDate >DATETYPE</ServiceDate> <!-- optional -->
<SalesTaxCodeRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</SalesTaxCodeRef>
<OverrideItemAccountRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</OverrideItemAccountRef>
<Other1 >STRTYPE</Other1> <!-- optional -->
<Other2 >STRTYPE</Other2> <!-- optional -->
<LinkToTxn> <!-- optional -->
<TxnID >IDTYPE</TxnID> <!-- required -->
<TxnLineID >IDTYPE</TxnLineID> <!-- required -->
</LinkToTxn>
<DataExt> <!-- optional, may repeat -->
<OwnerID >GUIDTYPE</OwnerID> <!-- required -->
<DataExtName >STRTYPE</DataExtName> <!-- required -->
<DataExtValue >STRTYPE</DataExtValue> <!-- required -->
</DataExt>
</InvoiceLineAdd>
<!-- OR -->
<InvoiceLineGroupAdd> <!-- optional -->
<ItemGroupRef> <!-- required -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ItemGroupRef>
<Quantity >QUANTYPE</Quantity> <!-- optional -->
<UnitOfMeasure >STRTYPE</UnitOfMeasure> <!-- optional -->
<InventorySiteRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</InventorySiteRef>
<InventorySiteLocationRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</InventorySiteLocationRef>
<DataExt> <!-- optional, may repeat -->
<OwnerID >GUIDTYPE</OwnerID> <!-- required -->
<DataExtName >STRTYPE</DataExtName> <!-- required -->
<DataExtValue >STRTYPE</DataExtValue> <!-- required -->
</DataExt>
</InvoiceLineGroupAdd>
<!-- END OR -->
</InvoiceAdd>
<IncludeRetElement >STRTYPE</IncludeRetElement> <!-- optional, may repeat -->
</InvoiceAddRq>
<InvoiceAddRs statusCode="INTTYPE" statusSeverity="STRTYPE" statusMessage="STRTYPE">
<InvoiceRet> <!-- optional -->
<TxnID >IDTYPE</TxnID> <!-- required -->
<TimeCreated >DATETIMETYPE</TimeCreated> <!-- required -->
<TimeModified >DATETIMETYPE</TimeModified> <!-- required -->
<EditSequence >STRTYPE</EditSequence> <!-- required -->
<TxnNumber >INTTYPE</TxnNumber> <!-- optional -->
<CustomerRef> <!-- required -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</CustomerRef>
<ClassRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ClassRef>
<ARAccountRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ARAccountRef>
<TemplateRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</TemplateRef>
<TxnDate >DATETYPE</TxnDate> <!-- required -->
<RefNumber >STRTYPE</RefNumber> <!-- optional -->
<BillAddress> <!-- optional -->
<Addr1 >STRTYPE</Addr1> <!-- optional -->
<Addr2 >STRTYPE</Addr2> <!-- optional -->
<Addr3 >STRTYPE</Addr3> <!-- optional -->
<Addr4 >STRTYPE</Addr4> <!-- optional -->
<Addr5 >STRTYPE</Addr5> <!-- optional -->
<City >STRTYPE</City> <!-- optional -->
<State >STRTYPE</State> <!-- optional -->
<PostalCode >STRTYPE</PostalCode> <!-- optional -->
<Country >STRTYPE</Country> <!-- optional -->
<Note >STRTYPE</Note> <!-- optional -->
</BillAddress>
<BillAddressBlock> <!-- optional -->
<Addr1 >STRTYPE</Addr1> <!-- optional -->
<Addr2 >STRTYPE</Addr2> <!-- optional -->
<Addr3 >STRTYPE</Addr3> <!-- optional -->
<Addr4 >STRTYPE</Addr4> <!-- optional -->
<Addr5 >STRTYPE</Addr5> <!-- optional -->
</BillAddressBlock>
<ShipAddress> <!-- optional -->
<Addr1 >STRTYPE</Addr1> <!-- optional -->
<Addr2 >STRTYPE</Addr2> <!-- optional -->
<Addr3 >STRTYPE</Addr3> <!-- optional -->
<Addr4 >STRTYPE</Addr4> <!-- optional -->
<Addr5 >STRTYPE</Addr5> <!-- optional -->
<City >STRTYPE</City> <!-- optional -->
<State >STRTYPE</State> <!-- optional -->
<PostalCode >STRTYPE</PostalCode> <!-- optional -->
<Country >STRTYPE</Country> <!-- optional -->
<Note >STRTYPE</Note> <!-- optional -->
</ShipAddress>
<ShipAddressBlock> <!-- optional -->
<Addr1 >STRTYPE</Addr1> <!-- optional -->
<Addr2 >STRTYPE</Addr2> <!-- optional -->
<Addr3 >STRTYPE</Addr3> <!-- optional -->
<Addr4 >STRTYPE</Addr4> <!-- optional -->
<Addr5 >STRTYPE</Addr5> <!-- optional -->
</ShipAddressBlock>
<IsPending >BOOLTYPE</IsPending> <!-- optional -->
<IsFinanceCharge >BOOLTYPE</IsFinanceCharge> <!-- optional -->
<PONumber >STRTYPE</PONumber> <!-- optional -->
<TermsRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</TermsRef>
<DueDate >DATETYPE</DueDate> <!-- optional -->
<SalesRepRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</SalesRepRef>
<FOB >STRTYPE</FOB> <!-- optional -->
<ShipDate >DATETYPE</ShipDate> <!-- optional -->
<ShipMethodRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ShipMethodRef>
<Subtotal >AMTTYPE</Subtotal> <!-- optional -->
<ItemSalesTaxRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ItemSalesTaxRef>
<SalesTaxPercentage >PERCENTTYPE</SalesTaxPercentage> <!-- optional -->
<SalesTaxTotal >AMTTYPE</SalesTaxTotal> <!-- optional -->
<AppliedAmount >AMTTYPE</AppliedAmount> <!-- optional -->
<BalanceRemaining >AMTTYPE</BalanceRemaining> <!-- optional -->
<CurrencyRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</CurrencyRef>
<ExchangeRate >FLOATTYPE</ExchangeRate> <!-- optional -->
<BalanceRemainingInHomeCurrency >AMTTYPE</BalanceRemainingInHomeCurrency> <!-- optional -->
<Memo >STRTYPE</Memo> <!-- optional -->
<IsPaid >BOOLTYPE</IsPaid> <!-- optional -->
<CustomerMsgRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</CustomerMsgRef>
<IsToBePrinted >BOOLTYPE</IsToBePrinted> <!-- optional -->
<IsToBeEmailed >BOOLTYPE</IsToBeEmailed> <!-- optional -->
<IsTaxIncluded >BOOLTYPE</IsTaxIncluded> <!-- optional -->
<CustomerSalesTaxCodeRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</CustomerSalesTaxCodeRef>
<SuggestedDiscountAmount >AMTTYPE</SuggestedDiscountAmount> <!-- optional -->
<SuggestedDiscountDate >DATETYPE</SuggestedDiscountDate> <!-- optional -->
<Other >STRTYPE</Other> <!-- optional -->
<ExternalGUID >GUIDTYPE</ExternalGUID> <!-- optional -->
<LinkedTxn> <!-- optional, may repeat -->
<TxnID >IDTYPE</TxnID> <!-- required -->
<!-- TxnType may have one of the following values: ARRefundCreditCard, Bill, BillPaymentCheck, BillPaymentCreditCard, BuildAssembly, Charge, Check, CreditCardCharge, CreditCardCredit, CreditMemo, Deposit, Estimate, InventoryAdjustment, Invoice, ItemReceipt, JournalEntry, LiabilityAdjustment, Paycheck, PayrollLiabilityCheck, PurchaseOrder, ReceivePayment, SalesOrder, SalesReceipt, SalesTaxPaymentCheck, Transfer, VendorCredit, YTDAdjustment -->
<TxnType >ENUMTYPE</TxnType> <!-- required -->
<TxnDate >DATETYPE</TxnDate> <!-- required -->
<RefNumber >STRTYPE</RefNumber> <!-- optional -->
<!-- LinkType may have one of the following values: AMTTYPE, QUANTYPE -->
<LinkType >ENUMTYPE</LinkType> <!-- optional -->
<Amount >AMTTYPE</Amount> <!-- required -->
</LinkedTxn>
<!-- BEGIN OR -->
<InvoiceLineRet> <!-- optional -->
<TxnLineID >IDTYPE</TxnLineID> <!-- required -->
<ItemRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ItemRef>
<Desc >STRTYPE</Desc> <!-- optional -->
<Quantity >QUANTYPE</Quantity> <!-- optional -->
<UnitOfMeasure >STRTYPE</UnitOfMeasure> <!-- optional -->
<OverrideUOMSetRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</OverrideUOMSetRef>
<!-- BEGIN OR -->
<Rate >PRICETYPE</Rate> <!-- optional -->
<!-- OR -->
<RatePercent >PERCENTTYPE</RatePercent> <!-- optional -->
<!-- END OR -->
<ClassRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ClassRef>
<Amount >AMTTYPE</Amount> <!-- optional -->
<InventorySiteRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</InventorySiteRef>
<InventorySiteLocationRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</InventorySiteLocationRef>
<!-- BEGIN OR -->
<SerialNumber >STRTYPE</SerialNumber> <!-- optional -->
<!-- OR -->
<LotNumber >STRTYPE</LotNumber> <!-- optional -->
<!-- END OR -->
<ExpirationDateForSerialLotNumber>STRTYPE</ExpirationDateForSerialLotNumber>
<ServiceDate >DATETYPE</ServiceDate> <!-- optional -->
<SalesTaxCodeRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</SalesTaxCodeRef>
<Other1 >STRTYPE</Other1> <!-- optional -->
<Other2 >STRTYPE</Other2> <!-- optional -->
<DataExtRet> <!-- optional, may repeat -->
<OwnerID >GUIDTYPE</OwnerID> <!-- optional -->
<DataExtName >STRTYPE</DataExtName> <!-- required -->
<!-- DataExtType may have one of the following values: AMTTYPE, DATETIMETYPE, INTTYPE, PERCENTTYPE, PRICETYPE, QUANTYPE, STR1024TYPE, STR255TYPE -->
<DataExtType >ENUMTYPE</DataExtType> <!-- required -->
<DataExtValue >STRTYPE</DataExtValue> <!-- required -->
</DataExtRet>
</InvoiceLineRet>
<!-- OR -->
<InvoiceLineGroupRet> <!-- optional -->
<TxnLineID >IDTYPE</TxnLineID> <!-- required -->
<ItemGroupRef> <!-- required -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ItemGroupRef>
<Desc >STRTYPE</Desc> <!-- optional -->
<Quantity >QUANTYPE</Quantity> <!-- optional -->
<UnitOfMeasure >STRTYPE</UnitOfMeasure> <!-- optional -->
<OverrideUOMSetRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</OverrideUOMSetRef>
<IsPrintItemsInGroup >BOOLTYPE</IsPrintItemsInGroup> <!-- required -->
<TotalAmount >AMTTYPE</TotalAmount> <!-- required -->
<InvoiceLineRet> <!-- optional, may repeat -->
<TxnLineID >IDTYPE</TxnLineID> <!-- required -->
<ItemRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ItemRef>
<Desc >STRTYPE</Desc> <!-- optional -->
<Quantity >QUANTYPE</Quantity> <!-- optional -->
<UnitOfMeasure >STRTYPE</UnitOfMeasure> <!-- optional -->
<OverrideUOMSetRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</OverrideUOMSetRef>
<!-- BEGIN OR -->
<Rate >PRICETYPE</Rate> <!-- optional -->
<!-- OR -->
<RatePercent >PERCENTTYPE</RatePercent> <!-- optional -->
<!-- END OR -->
<ClassRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</ClassRef>
<Amount >AMTTYPE</Amount> <!-- optional -->
<InventorySiteRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</InventorySiteRef>
<InventorySiteLocationRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</InventorySiteLocationRef>
<!-- BEGIN OR -->
<SerialNumber >STRTYPE</SerialNumber> <!-- optional -->
<!-- OR -->
<LotNumber >STRTYPE</LotNumber> <!-- optional -->
<!-- END OR -->
<ExpirationDateForSerialLotNumber>STRTYPE</ExpirationDateForSerialLotNumber>
<ServiceDate >DATETYPE</ServiceDate> <!-- optional -->
<SalesTaxCodeRef> <!-- optional -->
<ListID >IDTYPE</ListID> <!-- optional -->
<FullName >STRTYPE</FullName> <!-- optional -->
</SalesTaxCodeRef>
<Other1 >STRTYPE</Other1> <!-- optional -->
<Other2 >STRTYPE</Other2> <!-- optional -->
<DataExtRet> <!-- optional, may repeat -->
<OwnerID >GUIDTYPE</OwnerID> <!-- optional -->
<DataExtName >STRTYPE</DataExtName> <!-- required -->
<!-- DataExtType may have one of the following values: AMTTYPE, DATETIMETYPE, INTTYPE, PERCENTTYPE, PRICETYPE, QUANTYPE, STR1024TYPE, STR255TYPE -->
<DataExtType >ENUMTYPE</DataExtType> <!-- required -->
<DataExtValue >STRTYPE</DataExtValue> <!-- required -->
</DataExtRet>
</InvoiceLineRet>
<DataExtRet> <!-- optional, may repeat -->
<OwnerID >GUIDTYPE</OwnerID> <!-- optional -->
<DataExtName >STRTYPE</DataExtName> <!-- required -->
<!-- DataExtType may have one of the following values: AMTTYPE, DATETIMETYPE, INTTYPE, PERCENTTYPE, PRICETYPE, QUANTYPE, STR1024TYPE, STR255TYPE -->
<DataExtType >ENUMTYPE</DataExtType> <!-- required -->
<DataExtValue >STRTYPE</DataExtValue> <!-- required -->
</DataExtRet>
</InvoiceLineGroupRet>
<!-- END OR -->
<DataExtRet> <!-- optional, may repeat -->
<OwnerID >GUIDTYPE</OwnerID> <!-- optional -->
<DataExtName >STRTYPE</DataExtName> <!-- required -->
<!-- DataExtType may have one of the following values: AMTTYPE, DATETIMETYPE, INTTYPE, PERCENTTYPE, PRICETYPE, QUANTYPE, STR1024TYPE, STR255TYPE -->
<DataExtType >ENUMTYPE</DataExtType> <!-- required -->
<DataExtValue >STRTYPE</DataExtValue> <!-- required -->
</DataExtRet>
</InvoiceRet>
<ErrorRecovery> <!-- optional -->
<!-- BEGIN OR -->
<ListID >IDTYPE</ListID> <!-- optional -->
<!-- OR -->
<OwnerID >GUIDTYPE</OwnerID> <!-- optional -->
<!-- OR -->
<TxnID >IDTYPE</TxnID> <!-- optional -->
<!-- END OR -->
<TxnNumber >INTTYPE</TxnNumber> <!-- optional -->
<EditSequence >STRTYPE</EditSequence> <!-- optional -->
<ExternalGUID >GUIDTYPE</ExternalGUID> <!-- optional -->
</ErrorRecovery>
</InvoiceAddRs>
</QBXMLMsgsRq>
</QBXML>

View File

@ -22,7 +22,7 @@ class ItemInventoryQuery(baseQBQuery):
self.includeRetElements_allowed = ["ListID", "FullName", "TimeCreated", "TimeModified", "EditSequence", "Name", "IsActive", "ClassRef", "ParentRef", "Sublevel", "BarCodeValue",
"ManufacturerPartNumber", "UnitOfMeasureSetRef", "IsTaxIncluded", "SalesTaxCodeRef", "SalesDesc,", "SalesPrice", "IncomeAccountRef",
"PurchaseDesc", "PurchaseCost", "PurchaseTaxCodeRef", "COGSAccountRef", "PrefVendorRef", "AssetAccountRef", "ReforderPoint", "Max", "QuantityOnHand",
"AcerageCost", "QuantityOnOrder", "QuantityOnSalesOrder",
"AverageCost", "QuantityOnOrder", "QuantityOnSalesOrder",
"ExternalGUID", "DataExtRet",
]
self.onError = "stopOnError"
@ -326,182 +326,267 @@ class InvoiceAdd(baseQBQuery):
if 'debug' in kwargs and isinstance(kwargs['debug'], bool):
self.class_debug=kwargs["debug"]
self.QBDict[self.classNameRq]={}
self.isRequiredFieldSatisfied = False
self.QBDict[self.classNameRq][self.__class__.__name__]={'@defMacro':'MACROTYPE'}
if 'CustomerRef_ListID' in kwargs:
if 'CustomerRef' in self.QBDict[self.classNameRq][self.__class__.__name__]:
self.QBDict[self.classNameRq][self.__class__.__name__]["CustomerRef"]['ListID']= kwargs['CustomerRef_ListID']
# self.QBDict[self.classNameRq]={}
# self.QBDict={}
print('before')
if len(args)==0:
self.create_data(kwargs)
self.qbdicttemp = self.QBDict.copy()
del self.QBDict[self.__class__.__name__]
self.QBDict[self.classNameRq]=self.qbdicttemp
else:
self.QBDict[self.classNameRq][self.__class__.__name__]["CustomerRef"]={'ListID': kwargs['CustomerRef_ListID']}
self.qbdictlist = []
for arg in args:
self.create_data(arg)
self.qbdictlist.append(self.QBDict.copy())
del self.QBDict[self.__class__.__name__]
self.QBDict[self.classNameRq]=self.qbdictlist
pprint.pprint(self.QBDict, sort_dicts=False)
def create_data(self, kwargs):
# print(kwargs)
self.isRequiredFieldSatisfied = False
# self.QBDict[self.__class__.__name__]={'@defMacro':'MACROTYPE'}
self.QBDict[self.__class__.__name__]={}
if 'CustomerRef_ListID' in kwargs:
if 'CustomerRef' in self.QBDict[self.__class__.__name__]:
self.QBDict[self.__class__.__name__]["CustomerRef"]['ListID']= kwargs['CustomerRef_ListID']
else:
self.QBDict[self.__class__.__name__]["CustomerRef"]={'ListID': kwargs['CustomerRef_ListID']}
self.isRequiredFieldSatisfied=True
if 'CustomerRef_FullName' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["CustomerRef"]={'FullName': kwargs['CustomerRef_FullName']}
self.QBDict[self.__class__.__name__]["CustomerRef"]={'FullName': kwargs['CustomerRef_FullName']}
self.isRequiredFieldSatisfied=True
if not self.isRequiredFieldSatisfied:
raise Exception("Need CustomerRef FullName and/or ListID")
if 'ClassRef_ListID' in kwargs:
if 'ClassRef' in self.QBDict[self.classNameRq][self.__class__.__name__]:
self.QBDict[self.classNameRq][self.__class__.__name__]["ClassRef"]['ListID']= kwargs['ClassRef_ListID']
if 'ClassRef' in self.QBDict[self.__class__.__name__]:
self.QBDict[self.__class__.__name__]["ClassRef"]['ListID']= kwargs['ClassRef_ListID']
else:
self.QBDict[self.classNameRq][self.__class__.__name__]["ClassRef"]={'ListID': kwargs['ClassRef_ListID']}
self.QBDict[self.__class__.__name__]["ClassRef"]={'ListID': kwargs['ClassRef_ListID']}
if 'ClassRef_FullName' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ClassRef"]={'FullName': kwargs['ClassRef_FullName']}
self.QBDict[self.__class__.__name__]["ClassRef"]={'FullName': kwargs['ClassRef_FullName']}
if 'ARAccountRef_ListID' in kwargs:
if 'ARAccountRef' in self.QBDict[self.classNameRq][self.__class__.__name__]:
self.QBDict[self.classNameRq][self.__class__.__name__]["ARAccountRef"]['ListID']= kwargs['ARAccountRef_ListID']
if 'ARAccountRef' in self.QBDict[self.__class__.__name__]:
self.QBDict[self.__class__.__name__]["ARAccountRef"]['ListID']= kwargs['ARAccountRef_ListID']
else:
self.QBDict[self.classNameRq][self.__class__.__name__]["ARAccountRef"]={'ListID': kwargs['ARAccountRef_ListID']}
self.QBDict[self.__class__.__name__]["ARAccountRef"]={'ListID': kwargs['ARAccountRef_ListID']}
if 'ARAccountRef_FullName' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ARAccountRef"]={'FullName': kwargs['ARAccountRef_FullName']}
self.QBDict[self.__class__.__name__]["ARAccountRef"]={'FullName': kwargs['ARAccountRef_FullName']}
if 'TemplateRef_ListID' in kwargs:
if 'TemplateRef' in self.QBDict[self.classNameRq][self.__class__.__name__]:
self.QBDict[self.classNameRq][self.__class__.__name__]["TemplateRef"]['ListID']= kwargs['TemplateRef_ListID']
if 'TemplateRef' in self.QBDict[self.__class__.__name__]:
self.QBDict[self.__class__.__name__]["TemplateRef"]['ListID']= kwargs['TemplateRef_ListID']
else:
self.QBDict[self.classNameRq][self.__class__.__name__]["TemplateRef"]={'ListID': kwargs['TemplateRef_ListID']}
self.QBDict[self.__class__.__name__]["TemplateRef"]={'ListID': kwargs['TemplateRef_ListID']}
if 'TemplateRef_FullName' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["TemplateRef"]={'FullName': kwargs['TemplateRef_FullName']}
self.QBDict[self.__class__.__name__]["TemplateRef"]={'FullName': kwargs['TemplateRef_FullName']}
if 'TxnDate' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["TxnDate"]=kwargs['TxnDate']
self.QBDict[self.__class__.__name__]["TxnDate"]=kwargs['TxnDate']
if 'RefNumber' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["RefNumber"]=kwargs['RefNumber']
self.QBDict[self.__class__.__name__]["RefNumber"]=kwargs['RefNumber']
if 'BillAddress_Addr1' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["BillAddress"]={'Addr1': kwargs['BillAddress_Addr1']}
self.QBDict[self.__class__.__name__]["BillAddress"]={'Addr1': kwargs['BillAddress_Addr1']}
if 'BillAddress_Addr2' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["BillAddress"]={'Addr2': kwargs['BillAddress_Addr2']}
self.QBDict[self.__class__.__name__]["BillAddress"]={'Addr2': kwargs['BillAddress_Addr2']}
if 'BillAddress_Addr3' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["BillAddress"]={'Addr3': kwargs['BillAddress_Addr3']}
self.QBDict[self.__class__.__name__]["BillAddress"]={'Addr3': kwargs['BillAddress_Addr3']}
if 'BillAddress_Addr4' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["BillAddress"]={'Addr4': kwargs['BillAddress_Addr4']}
self.QBDict[self.__class__.__name__]["BillAddress"]={'Addr4': kwargs['BillAddress_Addr4']}
if 'BillAddress_Addr5' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["BillAddress"]={'Addr5': kwargs['BillAddress_Addr5']}
self.QBDict[self.__class__.__name__]["BillAddress"]={'Addr5': kwargs['BillAddress_Addr5']}
if 'BillAddress_City' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["BillAddress"]={'City': kwargs['BillAddress_City']}
self.QBDict[self.__class__.__name__]["BillAddress"]={'City': kwargs['BillAddress_City']}
if 'BillAddress_State' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["BillAddress"]={'State': kwargs['BillAddress_State']}
self.QBDict[self.__class__.__name__]["BillAddress"]={'State': kwargs['BillAddress_State']}
if 'BillAddress_PostalCode' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["BillAddress"]={'PostalCode': kwargs['BillAddress_PostalCode']}
self.QBDict[self.__class__.__name__]["BillAddress"]={'PostalCode': kwargs['BillAddress_PostalCode']}
if 'BillAddress_Country' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["BillAddress"]={'Country': kwargs['BillAddress_Country']}
self.QBDict[self.__class__.__name__]["BillAddress"]={'Country': kwargs['BillAddress_Country']}
if 'BillAddress_Note' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["BillAddress"]={'Note': kwargs['BillAddress_Note']}
self.QBDict[self.__class__.__name__]["BillAddress"]={'Note': kwargs['BillAddress_Note']}
if 'ShipAddress_Addr1' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipAddress"]={'Addr1': kwargs['ShipAddress_Addr1']}
self.QBDict[self.__class__.__name__]["ShipAddress"]={'Addr1': kwargs['ShipAddress_Addr1']}
if 'ShipAddress_Addr2' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipAddress"]={'Addr2': kwargs['ShipAddress_Addr2']}
self.QBDict[self.__class__.__name__]["ShipAddress"]={'Addr2': kwargs['ShipAddress_Addr2']}
if 'ShipAddress_Addr3' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipAddress"]={'Addr3': kwargs['ShipAddress_Addr3']}
self.QBDict[self.__class__.__name__]["ShipAddress"]={'Addr3': kwargs['ShipAddress_Addr3']}
if 'ShipAddress_Addr4' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipAddress"]={'Addr4': kwargs['ShipAddress_Addr4']}
self.QBDict[self.__class__.__name__]["ShipAddress"]={'Addr4': kwargs['ShipAddress_Addr4']}
if 'ShipAddress_Addr5' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipAddress"]={'Addr5': kwargs['ShipAddress_Addr5']}
self.QBDict[self.__class__.__name__]["ShipAddress"]={'Addr5': kwargs['ShipAddress_Addr5']}
if 'ShipAddress_City' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipAddress"]={'City': kwargs['ShipAddress_City']}
self.QBDict[self.__class__.__name__]["ShipAddress"]={'City': kwargs['ShipAddress_City']}
if 'ShipAddress_State' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipAddress"]={'State': kwargs['ShipAddress_State']}
self.QBDict[self.__class__.__name__]["ShipAddress"]={'State': kwargs['ShipAddress_State']}
if 'ShipAddress_PostalCode' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipAddress"]={'PostalCode': kwargs['ShipAddress_PostalCode']}
self.QBDict[self.__class__.__name__]["ShipAddress"]={'PostalCode': kwargs['ShipAddress_PostalCode']}
if 'ShipAddress_Country' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipAddress"]={'Country': kwargs['ShipAddress_Country']}
self.QBDict[self.__class__.__name__]["ShipAddress"]={'Country': kwargs['ShipAddress_Country']}
if 'ShipAddress_Note' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipAddress"]={'Note': kwargs['ShipAddress_Note']}
self.QBDict[self.__class__.__name__]["ShipAddress"]={'Note': kwargs['ShipAddress_Note']}
if 'IsPending' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["IsPending"]=kwargs['IsPending']
self.QBDict[self.__class__.__name__]["IsPending"]=kwargs['IsPending']
if 'IsFinanceCharge' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["IsFinanceCharge"]=kwargs['IsFinanceCharge']
self.QBDict[self.__class__.__name__]["IsFinanceCharge"]=kwargs['IsFinanceCharge']
if 'PONumber' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["PONumber"]=kwargs['PONumber']
self.QBDict[self.__class__.__name__]["PONumber"]=kwargs['PONumber']
if 'TermsRef_ListID' in kwargs:
if 'TermsRef' in self.QBDict[self.classNameRq][self.__class__.__name__]:
self.QBDict[self.classNameRq][self.__class__.__name__]["TermsRef"]['ListID']= kwargs['TermsRef_ListID']
if 'TermsRef' in self.QBDict[self.__class__.__name__]:
self.QBDict[self.__class__.__name__]["TermsRef"]['ListID']= kwargs['TermsRef_ListID']
else:
self.QBDict[self.classNameRq][self.__class__.__name__]["TermsRef"]={'ListID': kwargs['TermsRef_ListID']}
self.QBDict[self.__class__.__name__]["TermsRef"]={'ListID': kwargs['TermsRef_ListID']}
if 'TermsRef_FullName' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["TermsRef"]={'FullName': kwargs['TermsRef_FullName']}
self.QBDict[self.__class__.__name__]["TermsRef"]={'FullName': kwargs['TermsRef_FullName']}
if 'DueDate' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["DueDate"]=kwargs['DueDate']
self.QBDict[self.__class__.__name__]["DueDate"]=kwargs['DueDate']
if 'SalesRepRef_ListID' in kwargs:
if 'SalesRepRef' in self.QBDict[self.classNameRq][self.__class__.__name__]:
self.QBDict[self.classNameRq][self.__class__.__name__]["SalesRepRef"]['ListID']= kwargs['SalesRepRef_ListID']
if 'SalesRepRef' in self.QBDict[self.__class__.__name__]:
self.QBDict[self.__class__.__name__]["SalesRepRef"]['ListID']= kwargs['SalesRepRef_ListID']
else:
self.QBDict[self.classNameRq][self.__class__.__name__]["SalesRepRef"]={'ListID': kwargs['SalesRepRef_ListID']}
self.QBDict[self.__class__.__name__]["SalesRepRef"]={'ListID': kwargs['SalesRepRef_ListID']}
if 'SalesRepRef_FullName' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["SalesRepRef"]={'FullName': kwargs['SalesRepRef_FullName']}
self.QBDict[self.__class__.__name__]["SalesRepRef"]={'FullName': kwargs['SalesRepRef_FullName']}
if 'FOB' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["FOB"]=kwargs['FOB']
self.QBDict[self.__class__.__name__]["FOB"]=kwargs['FOB']
if 'ShipDate' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipDate"]=kwargs['ShipDate']
self.QBDict[self.__class__.__name__]["ShipDate"]=kwargs['ShipDate']
if 'ShipMethodRef_ListID' in kwargs:
if 'ShipMethodRef' in self.QBDict[self.classNameRq][self.__class__.__name__]:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipMethodRef"]['ListID']= kwargs['ShipMethodRef_ListID']
if 'ShipMethodRef' in self.QBDict[self.__class__.__name__]:
self.QBDict[self.__class__.__name__]["ShipMethodRef"]['ListID']= kwargs['ShipMethodRef_ListID']
else:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipMethodRef"]={'ListID': kwargs['ShipMethodRef_ListID']}
self.QBDict[self.__class__.__name__]["ShipMethodRef"]={'ListID': kwargs['ShipMethodRef_ListID']}
if 'ShipMethodRef_FullName' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ShipMethodRef"]={'FullName': kwargs['ShipMethodRef_FullName']}
self.QBDict[self.__class__.__name__]["ShipMethodRef"]={'FullName': kwargs['ShipMethodRef_FullName']}
if 'ItemSalesTaxRef_ListID' in kwargs:
if 'ItemSalesTaxRef' in self.QBDict[self.classNameRq][self.__class__.__name__]:
self.QBDict[self.classNameRq][self.__class__.__name__]["ItemSalesTaxRef"]['ListID']= kwargs['ItemSalesTaxRef_ListID']
if 'ItemSalesTaxRef' in self.QBDict[self.__class__.__name__]:
self.QBDict[self.__class__.__name__]["ItemSalesTaxRef"]['ListID']= kwargs['ItemSalesTaxRef_ListID']
else:
self.QBDict[self.classNameRq][self.__class__.__name__]["ItemSalesTaxRef"]={'ListID': kwargs['ItemSalesTaxRef_ListID']}
self.QBDict[self.__class__.__name__]["ItemSalesTaxRef"]={'ListID': kwargs['ItemSalesTaxRef_ListID']}
if 'ItemSalesTaxRef_FullName' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ItemSalesTaxRef"]={'FullName': kwargs['ItemSalesTaxRef_FullName']}
self.QBDict[self.__class__.__name__]["ItemSalesTaxRef"]={'FullName': kwargs['ItemSalesTaxRef_FullName']}
if 'Memo' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["Memo"]=kwargs['Memo']
self.QBDict[self.__class__.__name__]["Memo"]=kwargs['Memo']
if 'CustomerMsgRef_ListID' in kwargs:
if 'CustomerMsgRef' in self.QBDict[self.classNameRq][self.__class__.__name__]:
self.QBDict[self.classNameRq][self.__class__.__name__]["CustomerMsgRef"]['ListID']= kwargs['CustomerMsgRef_ListID']
if 'CustomerMsgRef' in self.QBDict[self.__class__.__name__]:
self.QBDict[self.__class__.__name__]["CustomerMsgRef"]['ListID']= kwargs['CustomerMsgRef_ListID']
else:
self.QBDict[self.classNameRq][self.__class__.__name__]["CustomerMsgRef"]={'ListID': kwargs['CustomerMsgRef_ListID']}
self.QBDict[self.__class__.__name__]["CustomerMsgRef"]={'ListID': kwargs['CustomerMsgRef_ListID']}
if 'CustomerMsgRef_FullName' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["CustomerMsgRef"]={'FullName': kwargs['CustomerMsgRef_FullName']}
self.QBDict[self.__class__.__name__]["CustomerMsgRef"]={'FullName': kwargs['CustomerMsgRef_FullName']}
if 'IsToBePrinted' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["IsToBePrinted"]=kwargs['IsToBePrinted']
self.QBDict[self.__class__.__name__]["IsToBePrinted"]=kwargs['IsToBePrinted']
if 'IsToBeEmailed' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["IsToBeEmailed"]=kwargs['IsToBeEmailed']
self.QBDict[self.__class__.__name__]["IsToBeEmailed"]=kwargs['IsToBeEmailed']
if 'IsTaxIncluded' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["IsTaxIncluded"]=kwargs['IsTaxIncluded']
self.QBDict[self.__class__.__name__]["IsTaxIncluded"]=kwargs['IsTaxIncluded']
if 'CustomerSalesTaxCodeRef_ListID' in kwargs:
if 'CustomerSalesTaxCodeRef' in self.QBDict[self.classNameRq][self.__class__.__name__]:
self.QBDict[self.classNameRq][self.__class__.__name__]["CustomerSalesTaxCodeRef"]['ListID']= kwargs['CustomerSalesTaxCodeRef_ListID']
if 'CustomerSalesTaxCodeRef' in self.QBDict[self.__class__.__name__]:
self.QBDict[self.__class__.__name__]["CustomerSalesTaxCodeRef"]['ListID']= kwargs['CustomerSalesTaxCodeRef_ListID']
else:
self.QBDict[self.classNameRq][self.__class__.__name__]["CustomerSalesTaxCodeRef"]={'ListID': kwargs['CustomerSalesTaxCodeRef_ListID']}
self.QBDict[self.__class__.__name__]["CustomerSalesTaxCodeRef"]={'ListID': kwargs['CustomerSalesTaxCodeRef_ListID']}
if 'CustomerSalesTaxCodeRef_FullName' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["CustomerSalesTaxCodeRef"]={'FullName': kwargs['CustomerSalesTaxCodeRef_FullName']}
self.QBDict[self.__class__.__name__]["CustomerSalesTaxCodeRef"]={'FullName': kwargs['CustomerSalesTaxCodeRef_FullName']}
if 'Other' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["Other"]=kwargs['Other']
self.QBDict[self.__class__.__name__]["Other"]=kwargs['Other']
if 'ExchangeRate' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ExchangeRate"]=kwargs['ExchangeRate']
self.QBDict[self.__class__.__name__]["ExchangeRate"]=kwargs['ExchangeRate']
if 'ExternalGUID' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["ExternalGUID"]=kwargs['ExternalGUID']
self.QBDict[self.__class__.__name__]["ExternalGUID"]=kwargs['ExternalGUID']
if 'LinkToTxnID' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["LinkToTxnID"]=makeAList(kwargs['LinkToTxnID'])
self.QBDict[self.__class__.__name__]["LinkToTxnID"]=makeAList(kwargs['LinkToTxnID'])
if 'SetCredit_CreditTxnID' in kwargs and 'SetCredit_AppliedAmount' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["SetCredit"]={'CreditTxnID':{'@useMacro':"MACROTYPE", '#text':kwargs['SetCredit_CreditTxnID']}, 'AppliedAmount': kwargs['SetCredit_AppliedAmount']}
self.QBDict[self.__class__.__name__]["SetCredit"]={'CreditTxnID':{'@useMacro':"MACROTYPE", '#text':kwargs['SetCredit_CreditTxnID']}, 'AppliedAmount': kwargs['SetCredit_AppliedAmount']}
if 'SetCredit_Override' in kwargs:
self.QBDict[self.classNameRq][self.__class__.__name__]["SetCredit"]["Override"]=kwargs['SetCredit_Override']
#add InvoiceLineAdd kwargs here
self.QBDict[self.__class__.__name__]["SetCredit"]["Override"]=kwargs['SetCredit_Override']
#add InvoiceLineAdd kwargs here
self.InvoiceLineAdd = []
if 'InvoiceLineAdd' in kwargs:
LineAdd = kwargs.get('InvoiceLineAdd')
self.isLineAddOk = True
if isinstance(LineAdd, dict ):
LineAdd = [LineAdd]
elif isinstance(LineAdd, list):
pass
else:
self.isLineAddOk = False
if self.isLineAddOk: #check if each instance in the list are all dictionary.
for eachLineAdd in LineAdd:
if not isinstance(eachLineAdd, dict):
self.isLineAddOk = False
break
else:
print("InvoiceLineAdd Not OK. has to be lisst of dict or a dict")
if self.isLineAddOk: #if everything good
for eachLineAdd in LineAdd:
self.LineAddDict = {}
if 'ItemRef_ListID' in eachLineAdd:
if 'ItemRef' in self.QBDict[self.__class__.__name__]:
self.LineAddDict["ItemRef"]['ListID']= eachLineAdd['ItemRef_ListID']
else:
self.LineAddDict["ItemRef"]={'ListID': eachLineAdd['ItemRef_ListID']}
if 'ItemRef_FullName' in eachLineAdd:
self.LineAddDict["ItemRef"]={'FullName': eachLineAdd['ItemRef_FullName']}
if 'Desc' in eachLineAdd:
self.LineAddDict["Desc"]=eachLineAdd['Desc']
if 'Quantity' in eachLineAdd:
self.LineAddDict["Quantity"]=eachLineAdd['Quantity']
if 'UnitOfMeasure' in eachLineAdd:
self.LineAddDict["UnitOfMeasure"]=eachLineAdd['UnitOfMeasure']
if 'Rate' in eachLineAdd:
self.LineAddDict["Rate"]=eachLineAdd['Rate']
elif 'RatePercent' in eachLineAdd:
self.LineAddDict["RatePercent"]=eachLineAdd['RatePercent']
elif 'PriceLevelRef_ListID' in eachLineAdd:
if 'PriceLevelRef' in self.QBDict[self.__class__.__name__]:
self.LineAddDict["PriceLevelRef"]['ListID']= eachLineAdd['PriceLevelRef_ListID']
else:
self.LineAddDict["PriceLevelRef"]={'ListID': eachLineAdd['PriceLevelRef_ListID']}
elif 'PriceLevelRef_FullName' in eachLineAdd:
self.LineAddDict["PriceLevelRef"]={'FullName': eachLineAdd['PriceLevelRef_FullName']}
if 'Amount' in eachLineAdd:
self.LineAddDict["Amount"]=eachLineAdd['Amount']
# Others
if 'Other1' in eachLineAdd:
self.LineAddDict["Other1"]=eachLineAdd['Other1']
if 'Other2' in eachLineAdd:
self.LineAddDict["Other2"]=eachLineAdd['Other2']
if len(self.LineAddDict)>0:
self.InvoiceLineAdd.append(self.LineAddDict)
if 'LinkToTxn_TxnID' in eachLineAdd and 'LinkToTxn_TxnLineID' in eachLineAdd:
self.LineAddDict["LinkToTxn"]={'TxnID': eachLineAdd['LinkToTxn_TxnID'], 'TxnLineID': eachLineAdd['LinkToTxn_TxnLineID']}
#skip the rest, not too important
else:
print("InvoiceLineAdd has to be list of dict or a dict")
# print(f'{self.InvoiceLineAdd = }')
if len(self.InvoiceLineAdd)>0:
self.QBDict[self.__class__.__name__]['InvoiceLineAdd']=self.InvoiceLineAdd
if 'IncludeRetElement' in kwargs:
self.QBDict[self.classNameRq]["IncludeRetElement"]=kwargs['IncludeRetElement']
# print(self.classNameRq)
# print(self.QBDict)
pprint.pprint(self.QBDict, sort_dicts=False)
@ -902,7 +987,7 @@ class SalesOrderAdd(baseQBQuery):
# if 'SetCredit_Override' in kwargs:
# self.QBDict[self.classNameRq][self.__class__.__name__]["SetCredit"]["Override"]=kwargs['SetCredit_Override']
#add InvoiceLineAdd kwargs here
#add InvoiceLineAdd kwargs here
self.SalesOrderLineAdd = []
if 'SalesOrderLineAdd' in kwargs:
@ -975,6 +1060,11 @@ class SalesOrderAdd(baseQBQuery):
class SalesOrderQuery(baseQBQuery):
def __init__(self, *args, **kwargs):
if 'debug' in kwargs and isinstance(kwargs['debug'], bool):
self.class_debug=kwargs["debug"]
else:
self.class_debug=False
if self.class_debug:
print(f'{args = }')
print(f'{kwargs = }')
super().__init__(*args, **kwargs)
@ -990,8 +1080,7 @@ class SalesOrderQuery(baseQBQuery):
self.defaultFilterKey = "TxnID"
self.className = 'SalesOrderQuery' #Hardcoded because for check if self.__class__.__name__==self.className
self.classNameRq:str = self.__class__.__name__ + 'Rq'
if 'debug' in kwargs and isinstance(kwargs['debug'], bool):
self.class_debug=kwargs["debug"]
self.QBDict[self.classNameRq]={}
### End Required Variable. can put ENUM list below this (eg: self.ENUM_GeneralSummaryReportQuery=[])
@ -1057,6 +1146,7 @@ class SalesOrderQuery(baseQBQuery):
self.QBDict[self.classNameRq]["OwnerID"]=kwargs['OwnerID']
# print(self.classNameRq)
if self.class_debug:
print(self.QBDict)
if self.__class__.__name__==self.className:
self.runCheck() ### running the qbxml connection to get data ###
@ -1303,6 +1393,7 @@ if __name__ == "__main__":
@timing
def customerquery():
g= CustomerQuery(MaxReturned=3, IncludeRetElement=["fullname", "name", "CompanyName", "BillAddressBlock", "ShipAddressBlock", "Notes", "AdditionalNotesRet", 'creditlimit'])
g= CustomerQuery(MaxReturned=2, IncludeRetElement=["fullname", "name", "CompanyName", "BillAddressBlock", "ShipAddress", "ShipToAddress","Phone", "Notes", "AdditionalNotesRet", 'creditlimit'])
# g= CustomerQuery(MaxReturned=20, ActiveStatus="ActiveOnly", MatchCriterion="StartsWith", Name="to", IncludeRetElement=["fullname", "name", "billaddressblock", "currencyfilter"])
# print(g.IncludeRetElements_allowed)
print("init finish")
@ -1376,13 +1467,13 @@ if __name__ == "__main__":
print([y for y in x])
print(f"{x.get('Name')} : {len(x.get('PriceLevelPerItemRet'))}")
pricelevel()
# pricelevel()
# invoicequery()
# salesorderquery()
# transactionquery()
# pprint.pprint(InventoryStockStatusByVendor(), sort_dicts=False)
# iteminventoryquery()
# customerquery()
customerquery()
# readxmltodict()
# g=SalesOrderQuery(MaxReturned=1)
# print(len(None))

View File

@ -22,7 +22,7 @@ def timing(f):
class baseQBQuery:
def __init__(self, *args, **kwargs, ) -> None:
# print(f'{kwargs = }')
# print(f'{args = }')
print(f'{args = }')
self.QBXML = None
self.QBDict = {}
self.response_string = None
@ -42,10 +42,12 @@ class baseQBQuery:
self.statusMessage = ""
self.statusSeverity = ""
self.statusOk = False
if self.class_debug:
if self.__class__.__name__=="baseQBQuery":
print("baseqbquey same with classname")
else:
print("accessed from child class")
print("basequery is accessed from ", self.__class__.__name__ + "Rq")
# @timing
@ -73,12 +75,14 @@ class baseQBQuery:
# }
# }
firstKey = str(list(self.QBDict.keys())[0])
print(f'{firstKey = } {self.QBDict}')
dataDict["?qbxml"]["QBXML"] = {"QBXMLMsgsRq": { ### Example with multiple FullName Item ###
"@onError": self.onError,
firstKey: self.QBDict[firstKey]}}
# 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}"?')
if self.class_debug:
print(self.QBXML, type(self.QBXML))
return self.QBXML
@ -113,7 +117,7 @@ class baseQBQuery:
# print(xmltodict.parse(self.response_string))
self.varDict = xmltodict.parse(self.response_string)
if self.class_debug:
pprint.pprint("isDataOK", self.varDict)
print("isDataOK", self.varDict)
self.listOfDict.varDict = self.varDict
self.listOfDict.filterKey = ["@requestID"]
self.requestID = self.listOfDict.firstValue().get('@requestID',None)
@ -128,7 +132,7 @@ class baseQBQuery:
print(f'isDataOK -> {self.listOfDict.firstValue() = }')
if self.listOfDict.firstValue().get(self.retName,None)==None:
return False
if self.class_debug:
print(f'{self.statusCode = }, {self.statusMessage = }, {self.statusSeverity = }')
varDict = self.varDict['QBXML']['QBXMLMsgsRs'][self.__class__.__name__+"Rs"]
return True
@ -184,6 +188,7 @@ class baseQBQuery:
if self.Rs:
return True
if self.QBDict:
print('runcheck', self.QBDict)
self.create_QBXML()
if self.connect_to_quickbooks():
return True

568
exim.py Normal file
View File

@ -0,0 +1,568 @@
# from . import QBClasses
from pprint import pprint
# from QBClass.QBClasses import InvoiceQuery, SalesOrderQuery
from QBClass.QBClasses import InvoiceQuery, SalesOrderQuery
# import timeit
import time
import json
import pandas as pd
import numpy as np
import datetime
print('succes Loading modules')
def timer(func):
def wrapper(*args, **kwargs):
nonlocal total
start = time.time()
result = func(*args, **kwargs)
duration = time.time() - start
total += duration
print(f"Execution time: {duration} Total: {total}")
return result
total = 0
return wrapper
@timer
def get_all_so_from_invoice( FromTxnDate=None, ToTxnDate=None, MaxReturned=None,):
print(MaxReturned, FromTxnDate, ToTxnDate)
start = time.time()
print('Get Invoice Query List. Processing..... wait for at minute(1 month=90secs)')
if MaxReturned:
iq = InvoiceQuery(MaxReturned= MaxReturned, IncludeLinkedTxns='true', IncludeLineItems='true', debug=False)
elif FromTxnDate and ToTxnDate:
print('here')
iq = InvoiceQuery(TxnDateRangeFilter_FromTxnDate=FromTxnDate, TxnDateRangeFilter_ToTxnDate=ToTxnDate, IncludeLinkedTxns='true', IncludeLineItems='true', debug=False)
else:
iq = InvoiceQuery(TxnDateRangeFilter_FromTxnDate='2021-01-01', TxnDateRangeFilter_ToTxnDate='2021-03-30', IncludeLinkedTxns='true', IncludeLineItems='true', debug=False)
# pprint(iq.all(), sort_dicts=False)
# print(iq.all())
print(f"Execution time InvoiceQuery: {time.time()-start} {len(iq.all()) = }")
so_list = []
iq_list = []
dup_so_list = []
for idx, txn in enumerate(iq.all()):
# iq_list.append(txn)
# print(f"{idx = } {txn['RefNumber'] = } {txn['TxnDate'] = } {txn['Subtotal'] = } ")
if 'LinkedTxn' in txn:
# pprint(txn['LinkedTxn'], sort_dicts=False)
if not isinstance(txn['LinkedTxn'], list): #if there is no receive payment and only 1 linked traction, need to change to a list. RECORD it
txn_linkedTxn = [txn['LinkedTxn']]
else:
txn_linkedTxn = txn['LinkedTxn']
for linkedtxn in txn_linkedTxn:
if linkedtxn['TxnType']=='SalesOrder':
if linkedtxn['RefNumber'] not in so_list:
so_list.append(linkedtxn['RefNumber'])
else:
dup_so_list.append(linkedtxn['RefNumber'])
print(f'{dup_so_list = }')
print()
so_dict = {}
print(f"Execution time before SO: {time.time()-start}")
print('Get Sales Order Query List. Processing..... wait for at minute(1 month=130 secs)')
so = SalesOrderQuery(RefNumber = so_list, IncludeLinkedTxns='true', IncludeLineItems='true', debug=False)
duplicateSO = []
soWithNoLinkedTxn = []
print(f"Execution time SalesOrderQuery: {time.time()-start}")
for idx, txn in enumerate(so.all()):
if 'LinkedTxn' in txn:
if txn['RefNumber'] not in so_dict:
so_dict[txn['RefNumber']] = txn
else:
duplicateSO.append(txn['RefNumber'])
else:
soWithNoLinkedTxn.append(txn)
# pprint(so.all(), sort_dicts=False)
res = next(iter(so_dict))
# print(f'{so_dict[res] = }')
# pprint(so_dict[res])
print(f'{soWithNoLinkedTxn = }')
print(f'{len(iq.all()) = } {len(so.all()) = } {len(so_list) = } {len(dup_so_list) = } {len(so_dict) = }')
print(f'{duplicateSO = }')
print()
### start processing like below module ###
pass
return iq.all(), so_dict
@timer
def process():
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')
pprint(iq.all(), sort_dicts=False)
# print(iq.all())
nolinkInv = []
soNotInOneInv = []
for idx, txn in enumerate(iq.all()):
print(f"{idx = } {txn['RefNumber'] = } {txn['TxnDate'] = } {txn['Subtotal'] = } ")
# print(f"{txn['Subtotal'] = }")
if 'LinkedTxn' in txn:
# pprint(txn['LinkedTxn'], sort_dicts=False)
if not isinstance(txn['LinkedTxn'], list): #if there is no receive payment and only 1 linked traction, need to change to a list. RECORD it
txn_linkedTxn = [txn['LinkedTxn']]
else:
txn_linkedTxn = txn['LinkedTxn']
for linkedtxn in txn_linkedTxn:
try:
if linkedtxn['TxnType']=='SalesOrder':
so = SalesOrderQuery(RefNumber = linkedtxn['RefNumber'], IncludeLinkedTxns='true', debug=False)
is_soLinkedToOneInvoice = False
if 'LinkedTxn' in so.all():
if not isinstance(so.all()['LinkedTxn'], list):
# print(so.all())
so_linkedTxn = [so.all()['LinkedTxn']] #make a list
else:
so_linkedTxn = so.all()['LinkedTxn'] #just copy, already list
# print(so.all())
for solinkedtxn in so_linkedTxn:
# print(len(so_linkedTxn))
if solinkedtxn['TxnType']=='Invoice' and len(so_linkedTxn)==1:
# print(so.all()['RefNumber'], 'the only one SO')
is_soLinkedToOneInvoice=True
# pass
else:
is_soLinkedToOneInvoice=False
print(so.all()['RefNumber'], 'NOT the only One, this SO have other Invoice number') #make append to a list
soNotInOneInv.append(so.all()['RefNumber'])
if float(linkedtxn['Amount'])<0:
if so.all()['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
if so.all()['IsManuallyClosed'] == 'true':
pass
print(f"{so.all()['TxnID'] = } {so.all()['RefNumber'] = }")
else:
print('SO TotalAmount<>Amount in Invoice. not Manually closed and not fully Invoiced')
pprint(f'{linkedtxn = }', sort_dicts=False)
print(f"{so.all()['TxnID'] = } {so.all()['RefNumber'] = }")
print(so.all())
else:
pass # this SO is fully invoiced, starting process to export the details
else:
print('Linkedtxn amount is positif(should be negatif')
except Exception as e:
print('ERROR')
pprint(linkedtxn, sort_dicts=False)
print(f"{so.all()['TxnID'] = }")
print(so.all())
print(e)
break
else:
nolinkInv.append(txn)
print(f'{len(nolinkInv) = }')
@timer
def process_data(iq_list, so_dict):
print('process_data')
# 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')
# pprint(iq_list, sort_dicts=False)
# print(iq_list)
nolinkInv = []
soNotInOneInv = []
manuallyClosedSO = []
openSO = []
fullyInvoicedSO = []
so_list = [x for x in so_dict]
print(f'{len(so_list) = }')
result_iq_list = []
for idx, txn in enumerate(iq_list):
# print(f"{idx = } {txn['RefNumber'] = } {txn['TxnDate'] = } {txn['Subtotal'] = } ")
# print(f"{txn['Subtotal'] = }")
if 'LinkedTxn' in txn:
# pprint(txn['LinkedTxn'], sort_dicts=False)
if not isinstance(txn['LinkedTxn'], list): #if there is no receive payment and only 1 linked traction, need to change to a list. RECORD it
txn_linkedTxn = [txn['LinkedTxn']]
else:
txn_linkedTxn = txn['LinkedTxn']
for linkedtxn in txn_linkedTxn:
# try:
if linkedtxn['TxnType']=='SalesOrder':
try:
# so_list.remove(linkedtxn['RefNumber'])
# so = SalesOrderQuery(RefNumber = linkedtxn['RefNumber'], IncludeLinkedTxns='true', debug=False)
sodt = so_dict[linkedtxn['RefNumber']]
is_soLinkedToOneInvoice = False
if sodt['IsManuallyClosed']=='true':
manuallyClosedSO.append(sodt['RefNumber'])
if sodt['IsFullyInvoiced']=='true':
fullyInvoicedSO.append(sodt['RefNumber'])
if 'LinkedTxn' in sodt:
if not isinstance(sodt['LinkedTxn'], list):
# print(sodt)
so_linkedTxn = [sodt['LinkedTxn']] #make a list
else:
so_linkedTxn = sodt['LinkedTxn'] #just copy, already list
# print(sodt)
for solinkedtxn in so_linkedTxn:
# print(len(so_linkedTxn))
if solinkedtxn['TxnType']=='Invoice' and len(so_linkedTxn)==1:
# print(sodt['RefNumber'], 'the only one SO')
is_soLinkedToOneInvoice=True
# pass
else:
is_soLinkedToOneInvoice=False
print(sodt['RefNumber'], 'NOT the only One, this SO have other Invoice number') #make append to a list
soNotInOneInv.append(sodt['RefNumber'])
if float(linkedtxn['Amount'])<0:
# if sodt['TotalAmount']!=linkedtxn['Amount'][1:]:
# pass
# if is_soLinkedToOneInvoice: #maybe the SO is manually closed, check it item by item, find which item is not in invoice
# if sodt['IsManuallyClosed'] == 'true':
# pass
# print(f"{sodt['TxnID'] = } {sodt['RefNumber'] = }")
# manuallyClosedSO.append(sodt['RefNumber'])
# else:
# print('SO TotalAmount<>Amount in Invoice. not Manually closed and not fully Invoiced')
# pprint(f'{linkedtxn = }', sort_dicts=False)
# print(f"{sodt['TxnID'] = } {sodt['RefNumber'] = }")
# print(sodt)
# openSO.append(sodt['RefNumber'])
# else:
pass # this SO is fully invoiced, starting process to export the details
try:
if not isinstance(sodt['SalesOrderLineRet'],list):
sodt['SalesOrderLineRet'] = [sodt['SalesOrderLineRet']]
if not isinstance(txn['InvoiceLineRet'],list):
txn['InvoiceLineRet'] = [txn['InvoiceLineRet']]
for so_line in sodt['SalesOrderLineRet']:
checklist = ['ItemRef', ]
if len([ i for i in checklist if i in so_line])==0:
continue
sotxnlineid = so_line['TxnLineID']
soitemref_fullname = so_line.get('ItemRef',{}).get('FullName')
soquantity:str = so_line.get('Quantity')
# print(f'{soquantity = }')
sounitofmeasure = so_line.get('UnitOfMeasure')
# sooverrideuomsetref_fullname = so_line['OverrideUOMSetRef']['FullName']
sorate = so_line.get('Rate')
soamount = so_line.get('Amount')
soinvoiced = so_line.get('Invoiced')
soismanuallyclosed = so_line['IsManuallyClosed']
soother2 = so_line.get('Other2')
#check compare to the invoicelineret
for inv_line in txn['InvoiceLineRet']: #loop start from top in order
is_inv_so_line_ok = True
if 'soline' not in inv_line: #this line has no so link yet
if inv_line.get('ItemRef',{}).get('FullName') != soitemref_fullname:
continue
if inv_line.get('UnitOfMeasure') != sounitofmeasure:
print(f"{inv_line['ItemRef']['FullName'] = } {inv_line['UnitOfMeasure']=} != {sounitofmeasure=}")
is_inv_so_line_ok = False
#do convertion????
# continue
if soinvoiced and inv_line.get('Quantity',0)!=soinvoiced: #compre with the invoiced
print(f"{inv_line['ItemRef']['FullName'] = } {inv_line['Quantity']=} != {soquantity=}")
is_inv_so_line_ok = False
if 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) = }")
is_inv_so_line_ok = False
# if soamount:
# if float(inv_line.get('Amount',0))!=float(soamount):
# print(f"{txn['RefNumber']} {inv_line['ItemRef']['FullName'] = } {inv_line['Amount']=} != {soamount=}")
# is_inv_so_line_ok = False
if not is_inv_so_line_ok:
print(f"{inv_line['ItemRef']['FullName'] = } Some detail not equal")
continue
#add to the spesific invoiceline
inv_line['soline']= {'TxnID':sodt['TxnID'],
'RefNumber':sodt['RefNumber'],
'TxnDate':sodt['TxnDate'],
'TxnLineID': sotxnlineid,
'ItemRef_FullName':soitemref_fullname,
'Quantity':soquantity,
'UnitOfMeasure':sounitofmeasure,
'Rate':sorate,
'Amount':soamount,
'Invoiced':soinvoiced,
'IsManuallyClosed':soismanuallyclosed,
'Other2':soother2}
break
except Exception as e:
print(f"SO {sodt['RefNumber'] = } {txn['RefNumber'] = }")
print(f'ERROR: {e}')
else:
print('Linkedtxn amount is positif(should be negatif')
except Exception as e:
# print('ERROR')
# pprint(linkedtxn, sort_dicts=False)
# print(f"{sodt['TxnID'] = }")
print(f"{sodt['RefNumber'] = } {txn['RefNumber'] = }")
print(f'ERROR: {e}')
break
else:
nolinkInv.append(txn)
# c =next(iter(iq_list))
# print('TEST RESULT:')
# pprint(c, sort_dicts=False)
print(f'{len(nolinkInv) = }\n{nolinkInv = }\n{soNotInOneInv = }\n{manuallyClosedSO = }\n{openSO = }\n{len(fullyInvoicedSO) = }')
c = [item for item in so_list if item not in fullyInvoicedSO]
print(f'not fuuly invoice, leftover SO: {c}')
return iq_list
def checking_iqwith_so(iq_list):
if not iq_list:
return False
if not isinstance(iq_list,list):
iq_list = [iq_list]
inv_nolineret = []
inv_line_no_soline = []
inv_line_no_itemref = []
for txn in iq_list:
if 'InvoiceLineRet' not in txn:
print(f"{txn['RefNumber'] = } doesnt have InvoiceLineRet")
inv_nolineret.append(txn['RefNumber'])
continue
# if 'LinkedTxn'
if not isinstance(txn['InvoiceLineRet'], list):
txn['InvoiceLineRet'] = [txn['InvoiceLineRet']]
for idx, inv_line in enumerate(txn['InvoiceLineRet']):
if 'ItemRef' not in inv_line:
inv_line_no_itemref.append({'RefNumber':txn['RefNumber'],
'idx':idx,})
continue
if 'soline' in inv_line:
continue
if '400_Sales' not in inv_line['ItemRef']['FullName'] and 'Sales Promo Discount' not in inv_line['ItemRef']['FullName']:
inv_line_no_soline.append({'RefNumber':txn['RefNumber'],
'idx':idx,
'ItemRef_FullName':inv_line['ItemRef']['FullName'],
'Amount':inv_line['Amount']})
print(f'{inv_line_no_soline = }')
print(f'{inv_line_no_itemref = }')
print(f'{inv_nolineret = }')
if inv_line_no_soline or inv_line_no_itemref or inv_nolineret:
return False
else:
return True
def make_invoiceadd_dict(iq_list):
print('make_invoiceadd_dict')
# status = checking_iqwith_so(iq_list)
# print(status)
# if not status:
# return False
inv_nolineret = []
inv_line_no_soline = []
inv_line_no_itemref = []
invoiceaddlist = []
for inv_line in iq_list:
# if 'InvoiceLineRet' not in txn:
# print(f"{txn['RefNumber'] = } doesnt have InvoiceLineRet")
# inv_nolineret.append(txn['RefNumber'])
# continue
# if not isinstance(txn['InvoiceLineRet'], list):
# txn['InvoiceLineRet'] = [txn['InvoiceLineRet']]
# for idx, inv_line in enumerate(txn['InvoiceLineRet']):
invadddict = {}
# pprint(inv_line, sort_dicts=False)
invadddict['CustomerRef_FullName'] = inv_line['CustomerRef']['FullName']
invadddict['ARAccountRef_FullName']= inv_line['ARAccountRef']['FullName']
invadddict['TemplateRef_FullName'] = inv_line['TemplateRef']['FullName']
invadddict['TxnDate'] = inv_line['TxnDate']
invadddict['RefNumber'] = inv_line['RefNumber']
invadddict['BillAddress_Addr1'] = inv_line['BillAddress'].get('Addr1')
invadddict['BillAddress_Addr2'] = inv_line['BillAddress'].get('Addr2')
invadddict['BillAddress_Addr3'] = inv_line['BillAddress'].get('Addr3')
invadddict['BillAddress_Addr4'] = inv_line['BillAddress'].get('Addr4')
invadddict['BillAddress_Addr5'] = inv_line['BillAddress'].get('Addr5')
invadddict['BillAddress_City'] = inv_line['BillAddress'].get('City')
invadddict['BillAddress_State'] = inv_line['BillAddress'].get('State')
invadddict['BillAddress_PostalCode'] = inv_line['BillAddress'].get('PostalCode')
invadddict['BillAddress_Country'] = inv_line['BillAddress'].get('Country')
invadddict['BillAddress_Note'] = inv_line['BillAddress'].get('Note')
if 'ShipAddress' in inv_line:
invadddict['ShipAddress_Addr1'] = inv_line['ShipAddress'].get('Addr1')
invadddict['ShipAddress_Addr2'] = inv_line['ShipAddress'].get('Addr2')
invadddict['ShipAddress_Addr3'] = inv_line['ShipAddress'].get('Addr3')
invadddict['ShipAddress_Addr4'] = inv_line['ShipAddress'].get('Addr4')
invadddict['ShipAddress_Addr5'] = inv_line['ShipAddress'].get('Addr5')
invadddict['ShipAddress_City'] = inv_line['ShipAddress'].get('City')
invadddict['ShipAddress_State'] = inv_line['ShipAddress'].get('State')
invadddict['ShipAddress_PostalCode'] = inv_line['ShipAddress'].get('PostalCode')
invadddict['ShipAddress_Country'] = inv_line['ShipAddress'].get('Country')
invadddict['ShipAddress_Note'] = inv_line['ShipAddress'].get('Note')
if inv_line.get('PONumber'):
invadddict['PONumber'] = inv_line.get('PONumber')
invadddict['TermsRef_FullName'] = inv_line['TermsRef']['FullName']
invadddict['DueDate'] = inv_line['DueDate']
if 'SalesRepRef' in inv_line:
invadddict['SalesRepRef_FullName'] = inv_line['SalesRepRef']['FullName']
invadddict['ShipDate'] = inv_line['ShipDate']
if inv_line.get('Memo'):
invadddict['Memo'] = inv_line['Memo']
invadddict['IsToBePrinted'] = "false"
invadddict['IsToBeEmailed'] = "false"
if 'Other' in inv_line :
invadddict['Other'] = inv_line['Other']
#InvoiceLineAdd BEGIN
invoicelineadd_list = []
txnid_list = []
if not isinstance(inv_line['InvoiceLineRet'], list):
inv_line['InvoiceLineRet'] = [inv_line['InvoiceLineRet']]
for idx, invlineret in enumerate(inv_line['InvoiceLineRet']):
print(f'{invlineret = }')
if 'ItemRef' not in invlineret:
inv_line_no_itemref.append({'RefNumber':inv_line['RefNumber'],
'idx':idx,})
continue
invlineadd={}
if 'soline' not in invlineret:
invlineadd['ItemRef_FullName'] = invlineret['ItemRef']['FullName']
# invlineadd['Desc'] = invlineret['Desc']
if 'Quantity' in invlineret:
invlineadd['Quantity'] = invlineret['Quantity']
if 'UnitOfMeasure' in invlineret:
invlineadd['UnitOfMeasure'] = invlineret['UnitOfMeasure']
invlineadd['Rate'] = invlineret['Rate']
invlineadd['Amount'] = invlineret['Amount']
if 'Other1' in invlineret:
invlineadd['Other1'] = invlineret['Other1']
if 'Other2' in invlineret:
invlineadd['Other2'] = invlineret['Other2']
# print(f"{invlineadd = } {invlineret['ItemRef']['FullName']=}")
### WARNING, check with the real TxnID in new QB. Replace the soline TxnID and TxnLineID with New QB SalesOrder
if 'soline' in invlineret: ### WARNING, check with the real TxnID in new QB
invlineadd['LinkToTxn_TxnID'] = invlineret['soline']['TxnID']
invlineadd['LinkToTxn_TxnLineID'] = invlineret['soline']['TxnLineID']
txnid_list.append(invlineret['soline']['TxnID'])
invoicelineadd_list.append(invlineadd)
# print(invlineadd)
# print(invoicelineadd_list)
txnid = list(set(txnid_list))
# if txnid:
# invadddict['LinkToTxnID']=txnid
invadddict['InvoiceLineAdd'] = invoicelineadd_list
invoiceaddlist.append(invadddict)
pprint(invadddict, sort_dicts=False)
for x in invoiceaddlist:
if '10671' in x['RefNumber']:
pprint(x, sort_dicts=False)
break
# for y in x['InvoiceLineAdd']:
# if '10671' in y['ItemRef_FullName']:
# pprint(x, sort_dicts=False)
# break
print(f'{len(invoiceaddlist) = }')
def writeToFile(iq_list=None, so_dict=None, filename = "", suffix="", indent=2):
if not filename:
return False
try:
if iq_list:
if indent==None:
iq_list_json = json.dumps(iq_list)
else:
iq_list_json = json.dumps(iq_list, indent=indent)
with open(f"{filename}{suffix}.json", "w") as outfile:
outfile.write(iq_list_json)
if so_dict:
if indent==None:
so_dict_json = json.dumps(so_dict)
else:
so_dict_json = json.dumps(so_dict, indent=indent)
with open(f"{filename}_so_dict{suffix}.json", "w") as outfile:
outfile.write(so_dict_json)
return True
except Exception as e:
print(e)
return False
def readJsonFromFile(filename):
try:
with open(filename, "r") as infile:
_list = json.load(infile)
return _list
except Exception as e:
print(e)
return []
def get_last_date_of_month(stryearmonth:str):
# Get Last date of Month
# Using replace() + timedelta()
# initializing date
test_date = datetime.datetime.fromisoformat(stryearmonth)
# test_date = datetime.datetime(2018, 6, 4)
# printing original date
print("The original date is : " + str(test_date))
# 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?
make_invoiceadd_dict(iq_list)
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)

137
exim_testimport.py Normal file
View File

@ -0,0 +1,137 @@
dt2 = [{'CustomerRef_FullName': 'JM Abadi',
'ARAccountRef_FullName': 'Accounts Receivable',
'TemplateRef_FullName': 'DBW Invoice (11%)',
'TxnDate': '2022-08-26',
'RefNumber': '10671',
'BillAddress_Addr1': 'JM Abadi',
'BillAddress_Addr2': 'Jl. Raya Ps. Minggu No. 75',
'BillAddress_Addr3': None,
'BillAddress_Addr4': None,
'BillAddress_Addr5': None,
'BillAddress_City': None,
'BillAddress_State': None,
'BillAddress_PostalCode': None,
'BillAddress_Country': None,
'BillAddress_Note': None,
'ShipAddress_Addr1': 'JM Abadi',
'ShipAddress_Addr2': 'Jl. Raya Ps. Minggu No. 75',
'ShipAddress_Addr3': None,
'ShipAddress_Addr4': None,
'ShipAddress_Addr5': None,
'ShipAddress_City': None,
'ShipAddress_State': None,
'ShipAddress_PostalCode': None,
'ShipAddress_Country': None,
'ShipAddress_Note': None,
'TermsRef_FullName': '30 Hari',
'DueDate': '2022-09-25',
'SalesRepRef_FullName': 'W',
'ShipDate': '2022-08-26',
'IsToBePrinted': 'false',
'IsToBeEmailed': 'false',
'InvoiceLineAdd': [{'Quantity': '12',
'UnitOfMeasure': 'Box',
'Rate': '35000',
'Amount': '420000.00',
'LinkToTxn_TxnID': 'A289A-1661495309',
'LinkToTxn_TxnLineID': 'A289C-1661495309'},
{'Quantity': '6',
'UnitOfMeasure': 'Box',
'Rate': '122500',
'Amount': '735000.00',
'LinkToTxn_TxnID': 'A289A-1661495309',
'LinkToTxn_TxnLineID': 'A289D-1661495309'}]},
{'CustomerRef_FullName': 'JM Abadi',
'ARAccountRef_FullName': 'Accounts Receivable',
'TemplateRef_FullName': 'DBW Invoice (11%)',
'TxnDate': '2022-08-26',
'RefNumber': '10671',
'BillAddress_Addr1': 'JM Abadi',
'BillAddress_Addr2': 'Jl. Raya Ps. Minggu No. 75',
'BillAddress_Addr3': None,
'BillAddress_Addr4': None,
'BillAddress_Addr5': None,
'BillAddress_City': None,
'BillAddress_State': None,
'BillAddress_PostalCode': None,
'BillAddress_Country': None,
'BillAddress_Note': None,
'ShipAddress_Addr1': 'JM Abadi',
'ShipAddress_Addr2': 'Jl. Raya Ps. Minggu No. 75',
'ShipAddress_Addr3': None,
'ShipAddress_Addr4': None,
'ShipAddress_Addr5': None,
'ShipAddress_City': None,
'ShipAddress_State': None,
'ShipAddress_PostalCode': None,
'ShipAddress_Country': None,
'ShipAddress_Note': None,
'TermsRef_FullName': '30 Hari',
'DueDate': '2022-09-25',
'SalesRepRef_FullName': 'W',
'ShipDate': '2022-08-26',
'IsToBePrinted': 'false',
'IsToBeEmailed': 'false',
'InvoiceLineAdd': [{'Quantity': '12',
'UnitOfMeasure': 'Box',
'Rate': '35000',
'Amount': '420000.00',
'LinkToTxn_TxnID': 'A289A-1661495309',
'LinkToTxn_TxnLineID': 'A289C-1661495309'},
{'Quantity': '6',
'UnitOfMeasure': 'Box',
'Rate': '122500',
'Amount': '735000.00',
'LinkToTxn_TxnID': 'A289A-1661495309',
'LinkToTxn_TxnLineID': 'A289D-1661495309'}]}]
# print(dt)
dt = {'CustomerRef_FullName': 'JM Abadi',
'ARAccountRef_FullName': 'Accounts Receivable',
'TemplateRef_FullName': 'DBW Invoice (11%)',
'TxnDate': '2022-08-26',
'RefNumber': '10671',
'BillAddress_Addr1': 'JM Abadi',
'BillAddress_Addr2': 'Jl. Raya Ps. Minggu No. 75',
'BillAddress_Addr3': None,
'BillAddress_Addr4': None,
'BillAddress_Addr5': None,
'BillAddress_City': None,
'BillAddress_State': None,
'BillAddress_PostalCode': None,
'BillAddress_Country': None,
'BillAddress_Note': None,
'ShipAddress_Addr1': 'JM Abadi',
'ShipAddress_Addr2': 'Jl. Raya Ps. Minggu No. 75',
'ShipAddress_Addr3': None,
'ShipAddress_Addr4': None,
'ShipAddress_Addr5': None,
'ShipAddress_City': None,
'ShipAddress_State': None,
'ShipAddress_PostalCode': None,
'ShipAddress_Country': None,
'ShipAddress_Note': None,
'TermsRef_FullName': '30 Hari',
'DueDate': '2022-09-25',
'SalesRepRef_FullName': 'W',
'ShipDate': '2022-08-26',
'IsToBePrinted': 'false',
'IsToBeEmailed': 'false',
'InvoiceLineAdd': [{'Quantity': '12',
'UnitOfMeasure': 'Box',
'Rate': '35000',
'Amount': '420000.00',
'LinkToTxn_TxnID': 'A289A-1661495309',
'LinkToTxn_TxnLineID': 'A289C-1661495309'},
{'Quantity': '6',
'UnitOfMeasure': 'Box',
'Rate': '122500',
'Amount': '735000.00',
'LinkToTxn_TxnID': 'A289A-1661495309',
'LinkToTxn_TxnLineID': 'A289D-1661495309'}]}
from QBClass.QBClasses import InvoiceAdd
# IA = InvoiceAdd(**dt, debug=True)
IA = InvoiceAdd(*dt2, debug=True) #a list
print(IA.all())

View File

@ -265,6 +265,9 @@ async def get_generalsalesreport(request: Request):
getdict = json.loads(getdict)
except:
print('error get_gsr()')
if not getdict:
getdict = {'ReportDateMacro' : 'ThisYear'}
else:
return {'message':'error getting GeneralSalesReport'}
print(f'get_gsr 1-> {type(getdict)}, {getdict}')
ReportDateMacro = getdict['ReportDateMacro'] if 'ReportDateMacro' in getdict else None
@ -274,7 +277,7 @@ async def get_generalsalesreport(request: Request):
responseRt = GSRQ(GeneralSummaryReportType='SalesByCustomerSummary', ReportDateMacro=ReportDateMacro, FromReportDate=FromReportDate, ToReportDate=ToReportDate)
# print(f'get_gsr 2-> {type(responseRt)}, {responseRt}')
datas1=responseRt.get_datarow()
# print(f'get_gsr 3-> {type(datas1)}, {datas1}')
print(f'get_gsr 3-> {type(datas1)}, {datas1}')
print(f'{datetime.datetime.now()} get_gsr 4 finish -> {type(getdict)}, {getdict}')
print("")

128
test from mike.py Normal file
View File

@ -0,0 +1,128 @@
import win32com.client
import xml.etree.ElementTree as ET
class QuickBooksSDK:
def __init__(self):
""" Initialize QBSDK Request Processor """
self.qb = win32com.client.Dispatch("QBXMLRP2.RequestProcessor")
# self.session_id = None
# def open_connection(self):
# """ Open connection to QuickBooks """
# self.qb.OpenConnection("", "My Python App")
# self.qb.BeginSession("", 2) # 2 = Use current QuickBooks session
# def close_connection(self):
# """ Close connection to QuickBooks """
# self.qb.EndSession()
# self.qb.CloseConnection()
def open_connection(self):
""" Open connection to QuickBooks """
self.qb = win32com.client.Dispatch("QBXMLRP2.RequestProcessor")
self.qb.OpenConnection("", "My QuickBooks App")
self.session_id = self.qb.BeginSession("", 2) # 2 = Open in "No UI" mode
print("Connection to QuickBooks established.", self.session_id)
def close_connection(self):
""" Close QuickBooks session and connection """
if self.session_id:
self.qb.EndSession(self.session_id)
self.qb.CloseConnection()
print("Connection to QuickBooks closed.")
# def send_request(self, qbxml: str) -> str:
# """ Send qbXML request and return response """
# print("Sending XML Request to QuickBooks:\n", qbxml) # Debugging print
# response = self.qb.ProcessRequest(qbxml)
# return response
def send_request(self, qbxml: str) -> str:
""" Send QBXML request to QuickBooks and return response """
try:
print("\n🔷 SENDING REQUEST TO QUICKBOOKS:")
print(qbxml) # Print the exact request
print(self.session_id)
response = self.qb.ProcessRequest(self.session_id, qbxml)
print("\n✅ RESPONSE RECEIVED FROM QUICKBOOKS:")
print(response if response else "No response received!")
return response
except Exception as e:
print("\n❌ ERROR Processing Request:", str(e))
return ""
def parse_sales_order_response(self, xml_response: str):
""" Parse SalesOrderQueryRs XML response into a Python dictionary """
print(f'{xml_response = }')
root = ET.fromstring(xml_response)
sales_orders = []
for order in root.findall(".//SalesOrderRet"):
order_data = {
"TxnID": order.findtext("TxnID", ""),
"TxnDate": order.findtext("TxnDate", ""),
"CustomerRef": order.findtext("CustomerRef/FullName", ""),
"TotalAmount": order.findtext("TotalAmount", ""),
"LineItems": []
}
for line in order.findall(".//SalesOrderLineRet"):
line_item = {
"ItemRef": line.findtext("ItemRef/FullName", ""),
"Quantity": line.findtext("Quantity", ""),
"Rate": line.findtext("Rate", ""),
"Amount": line.findtext("Amount", "")
}
order_data["LineItems"].append(line_item)
sales_orders.append(order_data)
return sales_orders
def get_sales_orders(self, from_date: str, to_date: str) -> str:
""" Fetch sales orders from QuickBooks within date range """
qbxml = f"""
<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="13.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<SalesOrderQueryRq requestID="1">
<TxnDateRangeFilter>
<FromTxnDate>2024-01-01</FromTxnDate>
<ToTxnDate>2024-01-05</ToTxnDate>
</TxnDateRangeFilter>
<IncludeLineItems>1</IncludeLineItems>
</SalesOrderQueryRq>
</QBXMLMsgsRq>
</QBXML>
"""
qbxml = qbxml.strip()
print("\n🔍 CHECKING QBXML FORMAT BEFORE SENDING:")
print(qbxml) # Print request before sending
response = self.send_request(qbxml)
return response
# **🔹 Main Execution**
if __name__ == "__main__":
qb = QuickBooksSDK()
try:
qb.open_connection()
# Query sales orders from January 1, 2024 to January 5, 2024
sales_orders = qb.get_sales_orders("2024-01-01", "2024-01-05")
# Print hasil dalam format dictionary
print("Sales Orders:", sales_orders)
finally:
qb.close_connection()

View File

@ -1,2 +0,0 @@
import icecream
print("berhasil")