From 13d140e9e928cfa4d751d005c7aaf31609855c67 Mon Sep 17 00:00:00 2001 From: bcomsugi Date: Wed, 8 Nov 2023 17:23:36 +0700 Subject: [PATCH 01/27] accomodate empty column in reading excel --- pdfexcel4DNwithxlrd.py | 48 ++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/pdfexcel4DNwithxlrd.py b/pdfexcel4DNwithxlrd.py index 8cb35a3..13c66af 100644 --- a/pdfexcel4DNwithxlrd.py +++ b/pdfexcel4DNwithxlrd.py @@ -158,10 +158,28 @@ def read_DN_excel(filename): for colidx, col in enumerate(x): ### change the empty cell into None if col == "": data[idx][colidx]=None - - # for idx, x in enumerate(data): - # print(idx, x) - + coly=0 + xylist=[] + for idx, x in enumerate(data): + print(idx, x) + xylist=[] + if len(x)>5 and (idx % 2)==1 : + print(idx,x) + for idy, y in enumerate(x): + if y == None: + coly=idy + else: + xylist.append(y) + if len(xylist)==5: + data[idx]=xylist + elif coly !=0: + for idy, y in enumerate(x): + if idy!=coly: + xylist.append(y) + data[idx]=xylist + coly=0 + print(idx, data[idx]) + print(f'len data={len(data)}') @@ -189,11 +207,11 @@ def read_DN_excel(filename): dt.append(uom) dt[2]=int(dt[2].split(".")[0]) templist=dt - # print(templist) + print(templist) - # for idx, x in enumerate(newdata): - # print(idx, x) - # print(f'len newdata={len(newdata)}') + for idx, x in enumerate(newdata): + print(idx, x) + print(f'len newdata={len(newdata)}') df=pd.DataFrame(newdata, columns=['Item No', 'Description', 'Quantity', 'No.SO/Ext.Doc.No.', 'LPN No.', 'UOM', 'Ext.Doc.No.'])#, columns=data[0]+"UOM") @@ -204,15 +222,16 @@ def read_DN_excel(filename): # print(df) # df['FullName'] = inteminvdf.loc[df['Item No'],'FullName'] df=df.merge(inteminvdf, how="left") - + print(df['FullName'].isnull()) + print(df['FullName']) # print(df) if df['FullName'].isnull().sum() > 0: print("Cannot Find Item FullName") listitemNoFullName = df.loc[df['FullName'].isnull()].values.tolist() df=df.reindex(columns=['Ext.Doc.No.', 'No.SO/Ext.Doc.No.', 'Item No', 'FullName', 'Quantity', 'UOM']) - print(df) - print(listitemNoFullName) + # print(df) + # print(listitemNoFullName) # print(listitemNoFullName) return False, listitemNoFullName else: @@ -232,5 +251,8 @@ if __name__=="__main__": # read_DN_excel(filename) # filename = "DN_Excel_files\TCO-DNPR-2305-00305.xls" # read_DN_excel(filename) - filename = "DN_Excel_files\TCO-DNPG-2307-01407.xls" - read_DN_excel(filename) \ No newline at end of file + # filename = "DN_Excel_files\TCO-DNPG-2307-01407.xls" + filename = "DN_Excel_files\TCO-DNPG-2310-00337.xls" + status, retdict = read_DN_excel(filename) + print(status) + print(retdict) \ No newline at end of file From c723c7bd62e43fb711b55ba54c63b1d26735989d Mon Sep 17 00:00:00 2001 From: bcomsugi Date: Thu, 9 Nov 2023 00:57:42 +0700 Subject: [PATCH 02/27] update --- SO_to_Inv/readSO.py | 16 ++++++++++++---- django/Invoice/urls.py | 3 ++- django/Invoice/views.py | 5 ++++- django/manage.py | 3 +++ 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/SO_to_Inv/readSO.py b/SO_to_Inv/readSO.py index 794ee7f..74822d7 100644 --- a/SO_to_Inv/readSO.py +++ b/SO_to_Inv/readSO.py @@ -8,7 +8,9 @@ from datetime import date import timeit import os import pythoncom +# from icecream import ic +ic.configureOutput(includeContext=True, ) class SalesOrderQuery: def __init__(self, **kwargs) -> None: # print(f'kwargs:{kwargs}') @@ -260,7 +262,7 @@ class SalesOrderQuery: def _get_sales_order_header(self, response_string): print('_get_sales_order_header') - # print(f'responsestring:{response_string}') + ic(f'responsestring:{response_string}') QBXML = ET.fromstring(response_string) datadict = {} SalesOrderdict = {} @@ -279,12 +281,18 @@ class SalesOrderQuery: SalesOrderdict = {'RefNumber':RefNumber, 'CustomerFullName':CustomerFullName, 'TxnID':TxnID, 'TotalAmount':TotalAmount, 'IsFullyInvoiced':IsFullyInvoiced, 'IsManuallyClosed':IsManuallyClosed, 'SalesOrderLineRet':[]} SalesOrderLineRet = SalesOrderRet.findall('SalesOrderLineRet') - # print(len(SalesOrderLineRet)) + ic(len(SalesOrderLineRet)) if len(SalesOrderLineRet) > 0: disc_amount=0 for SalesOrderLineRet in SalesOrderLineRet: TxnLineID = SalesOrderLineRet.find('TxnLineID').text - ItemFullName = SalesOrderLineRet.find('ItemRef/FullName').text + ItemFullName = SalesOrderLineRet.find('ItemRef/FullName') + if ItemFullName is None: + ic("no itemfullname") + break + else: + ItemFullName=ItemFullName.text + ic(ItemFullName) Quantity = SalesOrderLineRet.find('Quantity').text UnitOfMeasure = SalesOrderLineRet.find('UnitOfMeasure').text Rate = float(SalesOrderLineRet.find('Rate').text) @@ -293,7 +301,7 @@ class SalesOrderQuery: # if self.SPPriceLevelName: if self.Customer[2]: # print(Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.SPPriceLevelName)].values.tolist()[0][2])) - print(Quantity, Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2])) + ic(Quantity, Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2])) disc_amount += float(Quantity) * (Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) # disc_amount+=float(Quantity)*2000 #testing only Invoiced = SalesOrderLineRet.find('Invoiced').text diff --git a/django/Invoice/urls.py b/django/Invoice/urls.py index cd84006..744d2a5 100644 --- a/django/Invoice/urls.py +++ b/django/Invoice/urls.py @@ -1,6 +1,7 @@ from django.urls import path from . import views - +from icecream import install +install() app_name = "Invoice" urlpatterns = [ diff --git a/django/Invoice/views.py b/django/Invoice/views.py index 34eb062..9fd4b10 100644 --- a/django/Invoice/views.py +++ b/django/Invoice/views.py @@ -14,6 +14,9 @@ from django.contrib import messages import os import pandas as pd from django.conf import settings +from icecream import ic + +ic.configureOutput(includeContext= True) def get_SalesOrderQuery(customer_name): try: @@ -26,7 +29,7 @@ def get_SalesOrderQuery(customer_name): print("except") print(sys.path) from SO_to_Inv.readSO import SalesOrderQuery - + print("salesorderquery imported") # print(os.getcwd()) # parentdir = os.path.dirname(os.getcwd()) # print(parentdir) diff --git a/django/manage.py b/django/manage.py index feea57b..e950cdf 100644 --- a/django/manage.py +++ b/django/manage.py @@ -2,6 +2,9 @@ """Django's command-line utility for administrative tasks.""" import os import sys +from icecream import install +install() + def main(): From 2e22a01b52d18753bd282564d4429485d81493b1 Mon Sep 17 00:00:00 2001 From: bcomsugi Date: Sun, 12 Nov 2023 23:51:02 +0700 Subject: [PATCH 03/27] update discount correctly --- SO_to_Inv/readSO.py | 83 +++++++++++++++++++++++++++++++++++++++++- django/Invoice/urls.py | 2 + 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/SO_to_Inv/readSO.py b/SO_to_Inv/readSO.py index 74822d7..1e3114d 100644 --- a/SO_to_Inv/readSO.py +++ b/SO_to_Inv/readSO.py @@ -10,7 +10,7 @@ import os import pythoncom # from icecream import ic -ic.configureOutput(includeContext=True, ) +# ic.configureOutput(includeContext=True, ) class SalesOrderQuery: def __init__(self, **kwargs) -> None: # print(f'kwargs:{kwargs}') @@ -260,7 +260,7 @@ class SalesOrderQuery: return False, status_code - def _get_sales_order_header(self, response_string): + def _get_sales_order_header_(self, response_string): print('_get_sales_order_header') ic(f'responsestring:{response_string}') QBXML = ET.fromstring(response_string) @@ -272,6 +272,8 @@ class SalesOrderQuery: for SalesOrderRet in SalesOrderRets: RefNumber = SalesOrderRet.find('RefNumber').text # Memo = SalesOrderRet.find('Memo').text + TxnDate = SalesOrderRet.find('TxnDate').text + TxnNumber = SalesOrderRet.find('TxnNumber').text CustomerFullName = SalesOrderRet.find('CustomerRef/FullName').text TxnID = SalesOrderRet.find('TxnID').text TotalAmount = SalesOrderRet.find('TotalAmount').text @@ -279,6 +281,7 @@ class SalesOrderQuery: IsManuallyClosed = SalesOrderRet.find('IsManuallyClosed').text # print(CustomerFullName, TxnID, TotalAmount) SalesOrderdict = {'RefNumber':RefNumber, 'CustomerFullName':CustomerFullName, 'TxnID':TxnID, + 'TxnDate':TxnDate, 'TxnNumber':TxnNumber, 'TotalAmount':TotalAmount, 'IsFullyInvoiced':IsFullyInvoiced, 'IsManuallyClosed':IsManuallyClosed, 'SalesOrderLineRet':[]} SalesOrderLineRet = SalesOrderRet.findall('SalesOrderLineRet') ic(len(SalesOrderLineRet)) @@ -327,6 +330,82 @@ class SalesOrderQuery: # print(f'_get_sales_order_header->Salesorderlist: {self.SalesOrderList}') return self.SalesOrderList + + def _get_sales_order_header(self, response_string): + print('_get_sales_order_header_2') + ic(f'responsestring:{response_string}') + QBXML = ET.fromstring(response_string) + datadict = {} + SalesOrderdict = {} + _SalesOrderlist = [] + SalesOrderRets = QBXML.findall('.//SalesOrderRet') + # print(SalesOrderRets) + for SalesOrderRet in SalesOrderRets: + RefNumber = SalesOrderRet.find('RefNumber').text + # Memo = SalesOrderRet.find('Memo').text + TxnDate = SalesOrderRet.find('TxnDate').text + TxnNumber = SalesOrderRet.find('TxnNumber').text + CustomerFullName = SalesOrderRet.find('CustomerRef/FullName').text + TxnID = SalesOrderRet.find('TxnID').text + TotalAmount = SalesOrderRet.find('TotalAmount').text + IsFullyInvoiced = SalesOrderRet.find('IsFullyInvoiced').text + IsManuallyClosed = SalesOrderRet.find('IsManuallyClosed').text + # print(CustomerFullName, TxnID, TotalAmount) + SalesOrderdict = {'RefNumber':RefNumber, 'CustomerFullName':CustomerFullName, 'TxnID':TxnID, + 'TxnDate':TxnDate, 'TxnNumber':TxnNumber, + 'TotalAmount':TotalAmount, 'IsFullyInvoiced':IsFullyInvoiced, 'IsManuallyClosed':IsManuallyClosed, 'SalesOrderLineRet':[]} + SalesOrderLineRet = SalesOrderRet.findall('SalesOrderLineRet') + ic(len(SalesOrderLineRet)) + if len(SalesOrderLineRet) > 0: + disc_amount=0 + for SalesOrderLineRet in SalesOrderLineRet: + TxnLineID = SalesOrderLineRet.find('TxnLineID').text + ItemFullName = SalesOrderLineRet.find('ItemRef/FullName') + if ItemFullName is None: + ic("no itemfullname") + break + else: + ItemFullName=ItemFullName.text + ic(ItemFullName) + Quantity = SalesOrderLineRet.find('Quantity').text + UnitOfMeasure = SalesOrderLineRet.find('UnitOfMeasure').text + OverrideUOMSetRef = SalesOrderLineRet.find('OverrideUOMSetRef/FullName') + if OverrideUOMSetRef != None: + OverrideUOMSetRef = OverrideUOMSetRef.text + Rate = float(SalesOrderLineRet.find('Rate').text) + + Amount = float(SalesOrderLineRet.find('Amount').text) + # if self.SPPriceLevelName: + Invoiced = SalesOrderLineRet.find('Invoiced').text + LineIsManuallyClosed = SalesOrderLineRet.find('IsManuallyClosed').text + # print(TxnLineID, ItemFullName) + BackOrdered = float(Quantity) - float(Invoiced) + if BackOrdered and LineIsManuallyClosed.lower() == 'false' : + if self.Customer[2]: + # print(Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.SPPriceLevelName)].values.tolist()[0][2])) + ic(Quantity, BackOrdered, Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2])) + disc_amount += BackOrdered * (Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) + # disc_amount+=float(Quantity)*2000 #testing only + + SalesOrderLinedict = {'TxnLineID':TxnLineID, + 'ItemFullName':ItemFullName, + 'Quantity':Quantity, + 'UOM':UnitOfMeasure, + 'Rate':Rate, + 'Amount':Amount, + 'BackOrdered':BackOrdered, + 'Invoiced':Invoiced, + 'LineIsManuallyClosed':LineIsManuallyClosed, + } + SalesOrderdict['SalesOrderLineRet'].append(SalesOrderLinedict) + SalesOrderdict['Disc_Amount']=disc_amount + _SalesOrderlist.append(SalesOrderdict) + # print(_SalesOrderlist) + self.SalesOrderList=_SalesOrderlist + # print(f'_get_sales_order_header->Salesorderlist: {self.SalesOrderList}') + return self.SalesOrderList + + def addDiscountToInvoiceList(self, _dict:dict): print("addDiscountToInvoiceList") diff --git a/django/Invoice/urls.py b/django/Invoice/urls.py index 744d2a5..8f0e742 100644 --- a/django/Invoice/urls.py +++ b/django/Invoice/urls.py @@ -2,6 +2,8 @@ from django.urls import path from . import views from icecream import install install() +from icecream import ic +ic.configureOutput(includeContext=True, ) app_name = "Invoice" urlpatterns = [ From c160fc619b56ea31022b45b596a63e1719b09842 Mon Sep 17 00:00:00 2001 From: bcomsugi Date: Mon, 13 Nov 2023 00:57:24 +0700 Subject: [PATCH 04/27] _get_sales_order_header fixed disc --- SO_to_Inv/readSO.py | 85 +++++------------------------------------ django/Invoice/views.py | 1 + 2 files changed, 10 insertions(+), 76 deletions(-) diff --git a/SO_to_Inv/readSO.py b/SO_to_Inv/readSO.py index 1e3114d..eec1c68 100644 --- a/SO_to_Inv/readSO.py +++ b/SO_to_Inv/readSO.py @@ -260,7 +260,7 @@ class SalesOrderQuery: return False, status_code - def _get_sales_order_header_(self, response_string): + def _get_sales_order_header(self, response_string): print('_get_sales_order_header') ic(f'responsestring:{response_string}') QBXML = ET.fromstring(response_string) @@ -288,77 +288,7 @@ class SalesOrderQuery: if len(SalesOrderLineRet) > 0: disc_amount=0 for SalesOrderLineRet in SalesOrderLineRet: - TxnLineID = SalesOrderLineRet.find('TxnLineID').text - ItemFullName = SalesOrderLineRet.find('ItemRef/FullName') - if ItemFullName is None: - ic("no itemfullname") - break - else: - ItemFullName=ItemFullName.text - ic(ItemFullName) - Quantity = SalesOrderLineRet.find('Quantity').text - UnitOfMeasure = SalesOrderLineRet.find('UnitOfMeasure').text - Rate = float(SalesOrderLineRet.find('Rate').text) - - Amount = float(SalesOrderLineRet.find('Amount').text) - # if self.SPPriceLevelName: - if self.Customer[2]: - # print(Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.SPPriceLevelName)].values.tolist()[0][2])) - ic(Quantity, Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2])) - disc_amount += float(Quantity) * (Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) - # disc_amount+=float(Quantity)*2000 #testing only - Invoiced = SalesOrderLineRet.find('Invoiced').text - LineIsManuallyClosed = SalesOrderLineRet.find('IsManuallyClosed').text - # print(TxnLineID, ItemFullName) - BackOrdered = float(Quantity) - float(Invoiced) - if BackOrdered: - SalesOrderLinedict = {'TxnLineID':TxnLineID, - 'ItemFullName':ItemFullName, - 'Quantity':Quantity, - 'UOM':UnitOfMeasure, - 'Rate':Rate, - 'Amount':Amount, - 'BackOrdered':BackOrdered, - 'Invoiced':Invoiced, - 'LineIsManuallyClosed':LineIsManuallyClosed, - } - SalesOrderdict['SalesOrderLineRet'].append(SalesOrderLinedict) - SalesOrderdict['Disc_Amount']=disc_amount - _SalesOrderlist.append(SalesOrderdict) - # print(_SalesOrderlist) - self.SalesOrderList=_SalesOrderlist - # print(f'_get_sales_order_header->Salesorderlist: {self.SalesOrderList}') - return self.SalesOrderList - - - def _get_sales_order_header(self, response_string): - print('_get_sales_order_header_2') - ic(f'responsestring:{response_string}') - QBXML = ET.fromstring(response_string) - datadict = {} - SalesOrderdict = {} - _SalesOrderlist = [] - SalesOrderRets = QBXML.findall('.//SalesOrderRet') - # print(SalesOrderRets) - for SalesOrderRet in SalesOrderRets: - RefNumber = SalesOrderRet.find('RefNumber').text - # Memo = SalesOrderRet.find('Memo').text - TxnDate = SalesOrderRet.find('TxnDate').text - TxnNumber = SalesOrderRet.find('TxnNumber').text - CustomerFullName = SalesOrderRet.find('CustomerRef/FullName').text - TxnID = SalesOrderRet.find('TxnID').text - TotalAmount = SalesOrderRet.find('TotalAmount').text - IsFullyInvoiced = SalesOrderRet.find('IsFullyInvoiced').text - IsManuallyClosed = SalesOrderRet.find('IsManuallyClosed').text - # print(CustomerFullName, TxnID, TotalAmount) - SalesOrderdict = {'RefNumber':RefNumber, 'CustomerFullName':CustomerFullName, 'TxnID':TxnID, - 'TxnDate':TxnDate, 'TxnNumber':TxnNumber, - 'TotalAmount':TotalAmount, 'IsFullyInvoiced':IsFullyInvoiced, 'IsManuallyClosed':IsManuallyClosed, 'SalesOrderLineRet':[]} - SalesOrderLineRet = SalesOrderRet.findall('SalesOrderLineRet') - ic(len(SalesOrderLineRet)) - if len(SalesOrderLineRet) > 0: - disc_amount=0 - for SalesOrderLineRet in SalesOrderLineRet: + disc = 0 TxnLineID = SalesOrderLineRet.find('TxnLineID').text ItemFullName = SalesOrderLineRet.find('ItemRef/FullName') if ItemFullName is None: @@ -382,10 +312,12 @@ class SalesOrderQuery: BackOrdered = float(Quantity) - float(Invoiced) if BackOrdered and LineIsManuallyClosed.lower() == 'false' : if self.Customer[2]: - # print(Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.SPPriceLevelName)].values.tolist()[0][2])) - ic(Quantity, BackOrdered, Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2])) - disc_amount += BackOrdered * (Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) - # disc_amount+=float(Quantity)*2000 #testing only + disc = Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2] + # ic(Rate, disc, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.SPPriceLevelName)].values.tolist()[0][2])) + if disc > 0: + ic(Quantity, BackOrdered, Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2])) + disc_amount += BackOrdered * disc # (Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) + # disc_amount += BackOrdered * 2500#(Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) SalesOrderLinedict = {'TxnLineID':TxnLineID, 'ItemFullName':ItemFullName, @@ -396,6 +328,7 @@ class SalesOrderQuery: 'BackOrdered':BackOrdered, 'Invoiced':Invoiced, 'LineIsManuallyClosed':LineIsManuallyClosed, + 'disc':disc, } SalesOrderdict['SalesOrderLineRet'].append(SalesOrderLinedict) SalesOrderdict['Disc_Amount']=disc_amount diff --git a/django/Invoice/views.py b/django/Invoice/views.py index 9fd4b10..57c9e65 100644 --- a/django/Invoice/views.py +++ b/django/Invoice/views.py @@ -105,6 +105,7 @@ def show_inv(request): if itu: invoiceaddQBXML=ini.create_invoiceadd_QBXML() print(invoiceaddQBXML) + # print(ini.connect_to_quickbooks(ini.create_invoiceadd_QBXML())) return render( request, "Invoice/so_list_form.html", context) # return HttpResponse('') From bd0304b4095d8163b26fe9fbcd134883729d596d Mon Sep 17 00:00:00 2001 From: bcomsugi Date: Mon, 13 Nov 2023 01:07:45 +0700 Subject: [PATCH 05/27] update disc dict --- SO_to_Inv/readSO.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/SO_to_Inv/readSO.py b/SO_to_Inv/readSO.py index eec1c68..336e899 100644 --- a/SO_to_Inv/readSO.py +++ b/SO_to_Inv/readSO.py @@ -288,7 +288,8 @@ class SalesOrderQuery: if len(SalesOrderLineRet) > 0: disc_amount=0 for SalesOrderLineRet in SalesOrderLineRet: - disc = 0 + discPerItem = 0 + discPerPcs = 0 TxnLineID = SalesOrderLineRet.find('TxnLineID').text ItemFullName = SalesOrderLineRet.find('ItemRef/FullName') if ItemFullName is None: @@ -312,11 +313,13 @@ class SalesOrderQuery: BackOrdered = float(Quantity) - float(Invoiced) if BackOrdered and LineIsManuallyClosed.lower() == 'false' : if self.Customer[2]: - disc = Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2] + discPerPcs = Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2] # ic(Rate, disc, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.SPPriceLevelName)].values.tolist()[0][2])) - if disc > 0: + if discPerPcs > 0: ic(Quantity, BackOrdered, Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2])) - disc_amount += BackOrdered * disc # (Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) + discPerItem = BackOrdered * discPerPcs + disc_amount += discPerItem + # disc_amount += BackOrdered * discPerPcs # (Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) # disc_amount += BackOrdered * 2500#(Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) SalesOrderLinedict = {'TxnLineID':TxnLineID, @@ -328,7 +331,7 @@ class SalesOrderQuery: 'BackOrdered':BackOrdered, 'Invoiced':Invoiced, 'LineIsManuallyClosed':LineIsManuallyClosed, - 'disc':disc, + 'disc':discPerItem, # backorder qty * disc per pcs } SalesOrderdict['SalesOrderLineRet'].append(SalesOrderLinedict) SalesOrderdict['Disc_Amount']=disc_amount From f3b1cac25b89c088afe7e26b443d39b3bff11175 Mon Sep 17 00:00:00 2001 From: bcomsugi Date: Mon, 13 Nov 2023 01:40:15 +0700 Subject: [PATCH 06/27] update invoiceaddqbxml --- SO_to_Inv/readSO.py | 55 +++++++++++++++++++++++++---------------- django/Invoice/views.py | 2 +- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/SO_to_Inv/readSO.py b/SO_to_Inv/readSO.py index 336e899..5db9aa6 100644 --- a/SO_to_Inv/readSO.py +++ b/SO_to_Inv/readSO.py @@ -179,26 +179,38 @@ class SalesOrderQuery: disc_amount = 0 for soidx, salesorder in enumerate(self.SalesOrderList): SOTxnId = salesorder['TxnID'] - disc_amount+=int(salesorder['Disc_Amount']) + # disc_amount+=int(salesorder['Disc_Amount']) print(f'create_invoiceadd_QBXML->SOTxnId: {SOTxnId}') for itemline in salesorder['SalesOrderLineRet']: - # if 'DNQuantity' in itemline: - InvoiceLineAdd = self.create_sub_element(ET, InvoiceAdd, "InvoiceLineAdd", "\n ", 10 ) - # Quantity = self.create_sub_element(ET, InvoiceLineAdd, "Quantity", str(itemline['DNQuantity'] ), 12 ) - # Quantity = self.create_sub_element(ET, InvoiceLineAdd, "Quantity", str(itemline['BackOrdered'] ), 12 ) - # UnitOfMeasure = self.create_sub_element(ET, InvoiceLineAdd, "UnitOfMeasure", str(itemline['UOM']), 12 ) - LinkToTxn = self.create_sub_element(ET, InvoiceLineAdd, "LinkToTxn", "\n ", 10 ) - TxnID = self.create_sub_element(ET, LinkToTxn, "TxnID", SOTxnId,14 ) - TxnLineID = self.create_sub_element(ET, LinkToTxn, "TxnLineID", itemline['TxnLineID'], 12 ) - if soidx == len(self.SalesOrderList)-1: #last list then set the'400_Sales_discount' - print(f'disc_amount:{format(disc_amount, ".2f")}') - if disc_amount != 0: - - # disc_amount=format(disc_amount, ".2f") + backOrdered = str(itemline['BackOrdered']) + # backOrdered = '1' #testing purpose + if float(backOrdered) > 0: + discPerPcs = float(itemline['discPerPcs']) + discPerItem = float(backOrdered) * discPerPcs + disc_amount += discPerItem InvoiceLineAdd = self.create_sub_element(ET, InvoiceAdd, "InvoiceLineAdd", "\n ", 10 ) - ItemRef = self.create_sub_element(ET, InvoiceLineAdd, "ItemRef", "\n ", 12) - ItemFullName = self.create_sub_element(ET, ItemRef, "FullName", "400_Sales Discount", 12) - ItemRate = self.create_sub_element(ET, InvoiceLineAdd, "Rate", str(disc_amount), 10) + # Quantity = self.create_sub_element(ET, InvoiceLineAdd, "Quantity", str(itemline['DNQuantity'] ), 12 ) + Quantity = self.create_sub_element(ET, InvoiceLineAdd, "Quantity", backOrdered, 12 ) + # UnitOfMeasure = self.create_sub_element(ET, InvoiceLineAdd, "UnitOfMeasure", str(itemline['UOM']), 12 ) + LinkToTxn = self.create_sub_element(ET, InvoiceLineAdd, "LinkToTxn", "\n ", 10 ) + TxnID = self.create_sub_element(ET, LinkToTxn, "TxnID", SOTxnId,14 ) + TxnLineID = self.create_sub_element(ET, LinkToTxn, "TxnLineID", itemline['TxnLineID'], 12 ) + # if soidx == len(self.SalesOrderList)-1: #last list then set the'400_Sales_discount' + # print(f'disc_amount:{format(disc_amount, ".2f")}') + # if disc_amount != 0: + + # # disc_amount=format(disc_amount, ".2f") + # InvoiceLineAdd = self.create_sub_element(ET, InvoiceAdd, "InvoiceLineAdd", "\n ", 10 ) + # ItemRef = self.create_sub_element(ET, InvoiceLineAdd, "ItemRef", "\n ", 12) + # ItemFullName = self.create_sub_element(ET, ItemRef, "FullName", "400_Sales Discount", 12) + # ItemRate = self.create_sub_element(ET, InvoiceLineAdd, "Rate", str(disc_amount), 10) + + if disc_amount != 0: + # disc_amount=format(disc_amount, ".2f") + InvoiceLineAdd = self.create_sub_element(ET, InvoiceAdd, "InvoiceLineAdd", "\n ", 10 ) + ItemRef = self.create_sub_element(ET, InvoiceLineAdd, "ItemRef", "\n ", 12) + ItemFullName = self.create_sub_element(ET, ItemRef, "FullName", "400_Sales Discount", 12) + ItemRate = self.create_sub_element(ET, InvoiceLineAdd, "Rate", str(disc_amount), 10) mydata = ET.tostring(root, encoding = "unicode") @@ -311,7 +323,7 @@ class SalesOrderQuery: LineIsManuallyClosed = SalesOrderLineRet.find('IsManuallyClosed').text # print(TxnLineID, ItemFullName) BackOrdered = float(Quantity) - float(Invoiced) - if BackOrdered and LineIsManuallyClosed.lower() == 'false' : + if BackOrdered > 0 and LineIsManuallyClosed.lower() == 'false' : if self.Customer[2]: discPerPcs = Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2] # ic(Rate, disc, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.SPPriceLevelName)].values.tolist()[0][2])) @@ -320,8 +332,8 @@ class SalesOrderQuery: discPerItem = BackOrdered * discPerPcs disc_amount += discPerItem # disc_amount += BackOrdered * discPerPcs # (Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) - # disc_amount += BackOrdered * 2500#(Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) - + else: + discPerPcs = 0 SalesOrderLinedict = {'TxnLineID':TxnLineID, 'ItemFullName':ItemFullName, 'Quantity':Quantity, @@ -331,7 +343,8 @@ class SalesOrderQuery: 'BackOrdered':BackOrdered, 'Invoiced':Invoiced, 'LineIsManuallyClosed':LineIsManuallyClosed, - 'disc':discPerItem, # backorder qty * disc per pcs + 'discPerItem':discPerItem, # backorder qty * disc per pcs + 'discPerPcs':discPerPcs, } SalesOrderdict['SalesOrderLineRet'].append(SalesOrderLinedict) SalesOrderdict['Disc_Amount']=disc_amount diff --git a/django/Invoice/views.py b/django/Invoice/views.py index 57c9e65..5ec6ea3 100644 --- a/django/Invoice/views.py +++ b/django/Invoice/views.py @@ -105,7 +105,7 @@ def show_inv(request): if itu: invoiceaddQBXML=ini.create_invoiceadd_QBXML() print(invoiceaddQBXML) - # print(ini.connect_to_quickbooks(ini.create_invoiceadd_QBXML())) + print(ini.connect_to_quickbooks(ini.create_invoiceadd_QBXML())) return render( request, "Invoice/so_list_form.html", context) # return HttpResponse('') From 2df3be79cc64d5386004690c0d48f8b3cf25dff0 Mon Sep 17 00:00:00 2001 From: bcomsugi Date: Mon, 13 Nov 2023 13:19:48 +0700 Subject: [PATCH 07/27] update pretty xml --- SO_to_Inv/readSO.py | 10 +++++++++- django/Invoice/views.py | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/SO_to_Inv/readSO.py b/SO_to_Inv/readSO.py index 5db9aa6..c76c9d3 100644 --- a/SO_to_Inv/readSO.py +++ b/SO_to_Inv/readSO.py @@ -198,7 +198,6 @@ class SalesOrderQuery: # if soidx == len(self.SalesOrderList)-1: #last list then set the'400_Sales_discount' # print(f'disc_amount:{format(disc_amount, ".2f")}') # if disc_amount != 0: - # # disc_amount=format(disc_amount, ".2f") # InvoiceLineAdd = self.create_sub_element(ET, InvoiceAdd, "InvoiceLineAdd", "\n ", 10 ) # ItemRef = self.create_sub_element(ET, InvoiceLineAdd, "ItemRef", "\n ", 12) @@ -219,7 +218,16 @@ class SalesOrderQuery: qbxml_query = qbxml_query + "\n" + mydata # print(f'create_invoiceadd_QBXML->Create_Invoiceadd_QBXML: {qbxml_query}') # print(f"replyfrom qbxml:{self.connect_to_quickbooks(qbxml_query)}") + # print([s for s in qbxml_query.split('\n') if s.strip(' ') != '']) + import xml.dom.minidom + # dom = xml.dom.minidom.parse(xml_fname) # or + dom = xml.dom.minidom.parseString(qbxml_query) + pretty_xml_as_string = dom.toprettyxml(" ").split('\n') + # pretty_xml_as_string = '\n'.join([s for s in pretty_xml_as_string if s.strip(' ') != ""]) + pretty_xml_as_string = '\n'.join([s for s in pretty_xml_as_string if s.strip() ]) + + print(pretty_xml_as_string) return qbxml_query diff --git a/django/Invoice/views.py b/django/Invoice/views.py index 5ec6ea3..57c9e65 100644 --- a/django/Invoice/views.py +++ b/django/Invoice/views.py @@ -105,7 +105,7 @@ def show_inv(request): if itu: invoiceaddQBXML=ini.create_invoiceadd_QBXML() print(invoiceaddQBXML) - print(ini.connect_to_quickbooks(ini.create_invoiceadd_QBXML())) + # print(ini.connect_to_quickbooks(ini.create_invoiceadd_QBXML())) return render( request, "Invoice/so_list_form.html", context) # return HttpResponse('') From 12a5574e783e3b27b5c14efc4e6d8a0ba6a44fbe Mon Sep 17 00:00:00 2001 From: bcomsugi Date: Mon, 13 Nov 2023 14:36:02 +0700 Subject: [PATCH 08/27] update requirements.txt --- requirements.txt | Bin 2364 -> 2420 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index ee719e715370f0b679aa060f3fecf44764c08828..e9fe8d867850a95c1fbfcc744683c775a76073fd 100644 GIT binary patch delta 112 zcmdlZ^hIdGB1XfFi!+%R4L9>LcQW$ZGT1U0GUzcFF_?hJ>7I8970MVD99dtkRR; tvC4pz88H|Dm4Or+Zsufjg(x!y3K~rIWmn_{X)*wtq{m>eIhXxBBLHlw78L*h delta 56 zcmV-80LTCI61) Date: Mon, 13 Nov 2023 15:11:14 +0700 Subject: [PATCH 09/27] update requirement no pyinstaller --- requirements.txt | Bin 2420 -> 2314 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index e9fe8d867850a95c1fbfcc744683c775a76073fd..cb4c48d8b7f55ffd4a8d0494a6b209a33a5e59ae 100644 GIT binary patch delta 12 Tcmew&)Frgx2iLnT8dLmophLkUA7Lk Date: Wed, 15 Nov 2023 23:58:41 +0700 Subject: [PATCH 10/27] pretty print and readso can accept RefNumber --- SO_to_Inv/readSO.py | 80 ++++++++++++++++++++++++++++---------------- main.py | 9 +++-- qbsalesorderquery.py | 4 +-- test.py | 2 ++ 4 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 test.py diff --git a/SO_to_Inv/readSO.py b/SO_to_Inv/readSO.py index c76c9d3..b349ca5 100644 --- a/SO_to_Inv/readSO.py +++ b/SO_to_Inv/readSO.py @@ -8,7 +8,8 @@ from datetime import date import timeit import os import pythoncom -# from icecream import ic +from icecream import ic + # ic.configureOutput(includeContext=True, ) class SalesOrderQuery: @@ -30,9 +31,10 @@ class SalesOrderQuery: self._df_customer = pd.read_excel(os.path.join(self.cwd, self.item_inventory_path, self.CustomerPriceLevelName_filename), usecols=['FullName', 'PriceLevelName', 'SPName'],) self._df_customer = self._df_customer.fillna('') print(self._df_customer) - - self.Customer = self._df_customer.loc[(self._df_customer["FullName"]==self.FullName)].values.tolist()[0] - print(f'Customer:{self.Customer}') + self.Customer = None + if self.FullName: + self.Customer = self._df_customer.loc[(self._df_customer["FullName"]==self.FullName)].values.tolist()[0] + print(f'Customer:{self.Customer}') self.DN = kwargs['DN'] if 'DN' in kwargs else {} self.Reuse = kwargs['Reuse'] if 'Reuse' in kwargs else None @@ -54,9 +56,23 @@ class SalesOrderQuery: # print(self.Reuse) # if not self.Reuse: # self.dfDN, self.ext_doc_no_list = self.get_ext_doc_no_list(self.DN) - # self.RefNumber = kwargs['RefNumber'] if 'RefNumber' in kwargs else self.ext_doc_no_list + self.RefNumber = kwargs['RefNumber'] if 'RefNumber' in kwargs else None # self.get_sales_order_header() - + + + def pprintXml(self, qbxml_query): + import xml.dom.minidom + from xml.sax.saxutils import escape + from lxml import etree + # dom = xml.dom.minidom.parse(xml_fname) # or + if isinstance(qbxml_query, str): + dom = xml.dom.minidom.parseString(qbxml_query) + pretty_xml_as_string = dom.toprettyxml(" ").split('\n') + pretty_xml_as_string = '\n'.join([s for s in pretty_xml_as_string if s.strip() ]) + # print(f'pprintxml:\n{pretty_xml_as_string}') + return pretty_xml_as_string + + def create_sub_element(self, ET, parentNode, thisNode, text="\n", whiteSpace = 0, attrib =None): if type(attrib) is not dict: attrib = {} @@ -81,10 +97,15 @@ class SalesOrderQuery: QBXMLMsgsRq.text = "\n " SalesOrderQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "SalesOrderQueryRq","\n " ) # SalesOrderType = self.create_sub_element(ET, SalesOrderQueryRq, 'SalesOrderType', self.SalesOrderType) - if self.FullName: + if self.RefNumber: + pass + RefNumberFilter = self.create_sub_element(ET, SalesOrderQueryRq, 'RefNumberFilter', "\n ",) + MatchCriterion = self.create_sub_element(ET,RefNumberFilter, 'MatchCriterion', "Contains",) + RefNumber = self.create_sub_element(ET, RefNumberFilter, 'RefNumber', self.RefNumber, ) + elif self.FullName: EntityFilter = self.create_sub_element(ET, SalesOrderQueryRq, 'EntityFilter', "\n ") FullName = self.create_sub_element(ET, EntityFilter, "FullName", self.FullName, 6) - if self.DateMacro: + elif self.DateMacro: TxnDateRangeFilter = self.create_sub_element(ET, SalesOrderQueryRq, "TxnDateRangeFilter", "\n ",) SalesOrderType = self.create_sub_element(ET, TxnDateRangeFilter, "DateMacro", self.DateMacro) # SalesOrderType = self.create_sub_element(ET, SalesOrderQueryRq, "DateMacro", self.DateMacro) @@ -220,14 +241,7 @@ class SalesOrderQuery: # print(f"replyfrom qbxml:{self.connect_to_quickbooks(qbxml_query)}") # print([s for s in qbxml_query.split('\n') if s.strip(' ') != '']) - import xml.dom.minidom - # dom = xml.dom.minidom.parse(xml_fname) # or - dom = xml.dom.minidom.parseString(qbxml_query) - pretty_xml_as_string = dom.toprettyxml(" ").split('\n') - # pretty_xml_as_string = '\n'.join([s for s in pretty_xml_as_string if s.strip(' ') != ""]) - pretty_xml_as_string = '\n'.join([s for s in pretty_xml_as_string if s.strip() ]) - - print(pretty_xml_as_string) + print(self.pprintXml(qbxml_query)) return qbxml_query @@ -282,12 +296,18 @@ class SalesOrderQuery: def _get_sales_order_header(self, response_string): print('_get_sales_order_header') - ic(f'responsestring:{response_string}') + print(f'responsestring:{self.pprintXml(response_string)}') QBXML = ET.fromstring(response_string) datadict = {} SalesOrderdict = {} _SalesOrderlist = [] SalesOrderRets = QBXML.findall('.//SalesOrderRet') + if self.Customer == None: + custtemp = QBXML.find('.//SalesOrderRet/CustomerRef/FullName') + if custtemp != None: + self.Customer = custtemp.text + self.Customer = self._df_customer.loc[(self._df_customer["FullName"]==self.Customer)].values.tolist()[0] + print(f'Customer:{self.Customer}') # print(SalesOrderRets) for SalesOrderRet in SalesOrderRets: RefNumber = SalesOrderRet.find('RefNumber').text @@ -332,16 +352,18 @@ class SalesOrderQuery: # print(TxnLineID, ItemFullName) BackOrdered = float(Quantity) - float(Invoiced) if BackOrdered > 0 and LineIsManuallyClosed.lower() == 'false' : - if self.Customer[2]: - discPerPcs = Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2] - # ic(Rate, disc, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.SPPriceLevelName)].values.tolist()[0][2])) - if discPerPcs > 0: - ic(Quantity, BackOrdered, Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2])) - discPerItem = BackOrdered * discPerPcs - disc_amount += discPerItem - # disc_amount += BackOrdered * discPerPcs # (Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) - else: - discPerPcs = 0 + ic(self.Customer) + if self.Customer: + if self.Customer[2]: + discPerPcs = Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2] + # ic(Rate, disc, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.SPPriceLevelName)].values.tolist()[0][2])) + if discPerPcs > 0: + ic(Quantity, BackOrdered, Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2])) + discPerItem = BackOrdered * discPerPcs + disc_amount += discPerItem + # disc_amount += BackOrdered * discPerPcs # (Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) + else: + discPerPcs = 0 SalesOrderLinedict = {'TxnLineID':TxnLineID, 'ItemFullName':ItemFullName, 'Quantity':Quantity, @@ -566,7 +588,9 @@ if __name__ == '__main__': # ini=SalesOrderQuery(FullName= '999 HPL', IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'IsManuallyClosed', 'IsFullyInvoiced']) # ini=SalesOrderQuery(FullName= 'YSM Interior', IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'TxnDate', 'RefNumber', 'IsManuallyClosed', 'IsFullyInvoiced','TotalAmount']) - ini=SalesOrderQuery(FullName= 'Abadi Serpong', IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'TxnDate', 'RefNumber', 'IsManuallyClosed', 'IsFullyInvoiced','TotalAmount']) + # ini=SalesOrderQuery(FullName= 'Abadi Serpong', IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'TxnDate', 'RefNumber', 'IsManuallyClosed', 'IsFullyInvoiced','TotalAmount']) + # ini=SalesOrderQuery(RefNumber = 'B23070685', FullName= 'Abadi Serpong', IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'TxnDate', 'RefNumber', 'IsManuallyClosed', 'IsFullyInvoiced','TotalAmount']) + ini=SalesOrderQuery(RefNumber = 'B23070685', IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'TxnDate', 'RefNumber', 'IsManuallyClosed', 'IsFullyInvoiced','TotalAmount']) # iya = ini.create_customerquery_QBXML() #pakai excel saja lebih cepat # print(iya) print(f'createQBXML:{ini.create_QBXML()}') diff --git a/main.py b/main.py index ad88de2..a2976d6 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,11 @@ from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates from fastapi import FastAPI, Request, UploadFile, Body - +# from icecream import install +# import icecream +# install() +# from icecream import ic +# ic.configureOutput(includeContext=True, ) import json from iteminventorydasa import QBStock import datetime @@ -13,7 +17,7 @@ import pdfexcel4DNwithxlrd from ItemInventoryQuery import ItemInventoryQuery from SO_to_Inv import readSO import os -from icecream import ic + import pprint # app = FastAPI() @@ -134,6 +138,7 @@ async def getopenso(request: Request, CustomerName: str = Body(...)): FullName = CustomerName['CustomerName'] print(FullName) ini=readSO.SalesOrderQuery(FullName= FullName, IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'TxnDate', 'RefNumber', 'IsManuallyClosed', 'IsFullyInvoiced','TotalAmount']) + print("selesai salesorder") open_sales_orders = ini.get_open_so() print(f'return opensalesorder:{open_sales_orders}') return open_sales_orders diff --git a/qbsalesorderquery.py b/qbsalesorderquery.py index 0a174fc..1cc2c10 100644 --- a/qbsalesorderquery.py +++ b/qbsalesorderquery.py @@ -58,7 +58,7 @@ class SalesOrderQuery: qbxml_query = """\n""" qbxml_query = qbxml_query + """""" qbxml_query = qbxml_query + "\n" + mydata - + print(qbxml_query) return qbxml_query def connect_to_quickbooks(self, qbxml_query): @@ -83,7 +83,7 @@ class SalesOrderQuery: def __str__(self, *args) -> str: # return str(self._get_datarow(self.connect_to_quickbooks(self.create_QBXML()))) - # print("__str__") + print("__str__") return str(self.get_datarow()) # return "hello" diff --git a/test.py b/test.py new file mode 100644 index 0000000..4085149 --- /dev/null +++ b/test.py @@ -0,0 +1,2 @@ +import icecream +print("berhasil") \ No newline at end of file From 15e510124eeefbcd3ccb92b707404307e60c3580 Mon Sep 17 00:00:00 2001 From: bcomsugi Date: Fri, 17 Nov 2023 16:29:29 +0700 Subject: [PATCH 11/27] update readso --- SO_to_Inv/readSO.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/SO_to_Inv/readSO.py b/SO_to_Inv/readSO.py index b349ca5..ee31368 100644 --- a/SO_to_Inv/readSO.py +++ b/SO_to_Inv/readSO.py @@ -8,7 +8,7 @@ from datetime import date import timeit import os import pythoncom -from icecream import ic +# from icecream import ic # ic.configureOutput(includeContext=True, ) @@ -324,7 +324,7 @@ class SalesOrderQuery: 'TxnDate':TxnDate, 'TxnNumber':TxnNumber, 'TotalAmount':TotalAmount, 'IsFullyInvoiced':IsFullyInvoiced, 'IsManuallyClosed':IsManuallyClosed, 'SalesOrderLineRet':[]} SalesOrderLineRet = SalesOrderRet.findall('SalesOrderLineRet') - ic(len(SalesOrderLineRet)) + # ic(len(SalesOrderLineRet)) if len(SalesOrderLineRet) > 0: disc_amount=0 for SalesOrderLineRet in SalesOrderLineRet: @@ -333,11 +333,11 @@ class SalesOrderQuery: TxnLineID = SalesOrderLineRet.find('TxnLineID').text ItemFullName = SalesOrderLineRet.find('ItemRef/FullName') if ItemFullName is None: - ic("no itemfullname") + print("no itemfullname") break else: ItemFullName=ItemFullName.text - ic(ItemFullName) + # print(ItemFullName) Quantity = SalesOrderLineRet.find('Quantity').text UnitOfMeasure = SalesOrderLineRet.find('UnitOfMeasure').text OverrideUOMSetRef = SalesOrderLineRet.find('OverrideUOMSetRef/FullName') @@ -352,13 +352,13 @@ class SalesOrderQuery: # print(TxnLineID, ItemFullName) BackOrdered = float(Quantity) - float(Invoiced) if BackOrdered > 0 and LineIsManuallyClosed.lower() == 'false' : - ic(self.Customer) + # ic(self.Customer) if self.Customer: if self.Customer[2]: discPerPcs = Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2] # ic(Rate, disc, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.SPPriceLevelName)].values.tolist()[0][2])) if discPerPcs > 0: - ic(Quantity, BackOrdered, Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2])) + print(Quantity, BackOrdered, Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2])) discPerItem = BackOrdered * discPerPcs disc_amount += discPerItem # disc_amount += BackOrdered * discPerPcs # (Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) From fcdd70c6ccb320bf61f48e461a033edb4c60470e Mon Sep 17 00:00:00 2001 From: Sugiarto Date: Tue, 5 Dec 2023 18:42:35 +0700 Subject: [PATCH 12/27] accomodate blank column --- pdfexcel4DNwithxlrd.py | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/pdfexcel4DNwithxlrd.py b/pdfexcel4DNwithxlrd.py index 13c66af..dd44422 100644 --- a/pdfexcel4DNwithxlrd.py +++ b/pdfexcel4DNwithxlrd.py @@ -108,7 +108,19 @@ def read_DN_excel(filename): if not None and row[0]=="Item No" : if firstpage: # print('firstpage') - data.append(row) + if len(row)==5: + data.append(row) + elif len(row)>5: + temp_ =[] + for _ in row: + if _ != None: + temp_.append(_) + if len(row)==5: + data.append(temp_) + else: + print("HEADER ERROR!!!") + data.append(['Item No', 'Description', 'QuantityUOM', 'No.SO/Ext.Doc.No.', 'LPN No.']) + boldataline=True firstpage=False # continue @@ -130,7 +142,8 @@ def read_DN_excel(filename): movetonextpage=True continue elif row[3] is not None: - if row[3].startswith('Hormat'): + # if row[3].startswith('Hormat'): + if 'Hormat Kami,' in row: # print('hormatkami found') boldataline=False movetonextpage=True @@ -140,7 +153,8 @@ def read_DN_excel(filename): else: data.append(row) elif row[3] is not None: - if row[3].startswith('Hormat'): + # if row[3].startswith('Hormat'): + if 'Hormat Kami,' in row: boldataline=False movetonextpage=True # continue @@ -159,25 +173,29 @@ def read_DN_excel(filename): if col == "": data[idx][colidx]=None coly=0 + lenList = 0 xylist=[] for idx, x in enumerate(data): print(idx, x) xylist=[] if len(x)>5 and (idx % 2)==1 : print(idx,x) + lenList = len(x) for idy, y in enumerate(x): if y == None: coly=idy + else: xylist.append(y) if len(xylist)==5: data[idx]=xylist - elif coly !=0: + elif coly != 0 and lenList == len(x): for idy, y in enumerate(x): if idy!=coly: xylist.append(y) data[idx]=xylist coly=0 + lenList = 0 print(idx, data[idx]) print(f'len data={len(data)}') @@ -188,7 +206,7 @@ def read_DN_excel(filename): templist=[] for idx, dt in enumerate(data): if dt[0] != 'Item No': - # print(idx,'not item') + # print(idx,'not item', dt) if dt[0] is None: if dt[1]: templist[1]+=" " + dt[1] @@ -207,10 +225,11 @@ def read_DN_excel(filename): dt.append(uom) dt[2]=int(dt[2].split(".")[0]) templist=dt - print(templist) + # print(templist) for idx, x in enumerate(newdata): - print(idx, x) + pass + # print(idx, x) print(f'len newdata={len(newdata)}') From 684cf74cc364dd3c94e0822d634b365c6eb57dc0 Mon Sep 17 00:00:00 2001 From: Sugiarto Date: Thu, 7 Dec 2023 10:28:55 +0700 Subject: [PATCH 13/27] update pdfexcel with reading column anomaly --- main.py | 3 ++- pdfexcel4DNwithxlrd.py | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/main.py b/main.py index a2976d6..8c4e34c 100644 --- a/main.py +++ b/main.py @@ -60,6 +60,7 @@ async def renew_iteminventory(): @app.post("/upload-file/") async def create_upload_file(uploaded_file: UploadFile): base_file_location = f"DN_Excel_files" + status = "ERROR" if uploaded_file.filename.endswith(".xls") and uploaded_file.filename.startswith("TCO-DN"): folder_yearmonth = uploaded_file.filename.split('-') if len(folder_yearmonth)>3: @@ -127,7 +128,7 @@ async def create_upload_file(uploaded_file: UploadFile): return [{"info": f"file '{uploaded_file.filename}' saved at '{file_location}'", "status": status, "msg": msg}] - return {"info": f"file '{uploaded_file.filename}' is not Excel(.xls) file or it is not Delivery Note(TCO-DN)file. please upload the correct file", "status": status} + return {"info": f"file '{uploaded_file.filename}' is not Excel(.xls) file or Filename is not start with 'TCO-DN'. Please upload the correct file", "status": status} @app.post('/getopenso') async def getopenso(request: Request, CustomerName: str = Body(...)): diff --git a/pdfexcel4DNwithxlrd.py b/pdfexcel4DNwithxlrd.py index dd44422..f86c46e 100644 --- a/pdfexcel4DNwithxlrd.py +++ b/pdfexcel4DNwithxlrd.py @@ -84,9 +84,25 @@ def read_DN_excel(filename): # DNRefNum = rawdata[1][3].strip().split("-")[1][-1] + "".join(rawdata[1][3].strip().split("-")[-2:]) # TxnDate = rawdata[2][3].strip().split(" ")[-1] - DNRefNum = wb.sheets()[0].cell(1, 3).value.strip().split("-")[1][-1] + "".join(wb.sheets()[0].cell(1, 3).value.strip().split("-")[-2:]) + _y=1 + _x=0 + for col in range(1,wb.sheets()[0].ncols): + + col_value = wb.sheets()[0].col_values(col) + print("col=",col, col_value[1]) + if "TCO-DN" in col_value[1]: + _x=col + if _x == 0 : + return False, "Cannot find TCO-DN cell" + + + # if "TCO-DN" in wb.sheets()[0].cell(_y, _x).value.strip(): + + + print(wb.sheets()[0].cell(_y, _x).value.strip()) + DNRefNum = wb.sheets()[0].cell(_y, _x).value.strip().split("-")[1][-1] + "".join(wb.sheets()[0].cell(_y, _x).value.strip().split("-")[-2:]) # print(DNRefNum) - TxnDate = wb.sheets()[0].cell(2, 3).value.strip().split(" ")[-1] + TxnDate = wb.sheets()[0].cell(_y+1, _x).value.strip().split(" ")[-1] Memo = DNRefNum print(f'pdfexcel4DNwithxlrd.py->DNRefNum:{DNRefNum}, TxnDate:{TxnDate}') DeliveryNotedict={'DNRefNum':DNRefNum, 'TxnDate':TxnDate, 'Memo': Memo} From 323be7c7e782beb8ba3147fa51a18dd21df91741 Mon Sep 17 00:00:00 2001 From: bcomsugi Date: Wed, 27 Dec 2023 04:23:20 +0700 Subject: [PATCH 14/27] update --- pdfexcel4DNwithxlrd.py | 14 +++++++------- qbpurchaseorderquery.py | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pdfexcel4DNwithxlrd.py b/pdfexcel4DNwithxlrd.py index dd44422..6220de6 100644 --- a/pdfexcel4DNwithxlrd.py +++ b/pdfexcel4DNwithxlrd.py @@ -119,7 +119,7 @@ def read_DN_excel(filename): data.append(temp_) else: print("HEADER ERROR!!!") - data.append(['Item No', 'Description', 'QuantityUOM', 'No.SO/Ext.Doc.No.', 'LPN No.']) + data.append(['Item No', 'Description', 'QuantityUOM', 'No.SO', 'LPN No.']) boldataline=True firstpage=False @@ -233,10 +233,10 @@ def read_DN_excel(filename): print(f'len newdata={len(newdata)}') - df=pd.DataFrame(newdata, columns=['Item No', 'Description', 'Quantity', 'No.SO/Ext.Doc.No.', 'LPN No.', 'UOM', 'Ext.Doc.No.'])#, columns=data[0]+"UOM") + df=pd.DataFrame(newdata, columns=['Item No', 'Description', 'Quantity', 'No.SO', 'LPN No.', 'UOM', 'Ext.Doc.No'])#, columns=data[0]+"UOM") # print(df) - # df=df.groupby(['No.SO/Ext.Doc.No.','Item No', 'UOM'])['Quantity'].sum().reset_index().sort_values(by=['Item No', 'No.SO/Ext.Doc.No.'])#.sort_values(by=['No.SO/Ext.Doc.No.']) - df=df.groupby(['Ext.Doc.No.', 'No.SO/Ext.Doc.No.','Item No', 'UOM'])['Quantity'].sum().reset_index().sort_values(by=['Ext.Doc.No.','No.SO/Ext.Doc.No.', 'Item No']) + # df=df.groupby(['No.SO','Item No', 'UOM'])['Quantity'].sum().reset_index().sort_values(by=['Item No', 'No.SO'])#.sort_values(by=['No.SO']) + df=df.groupby(['Ext.Doc.No', 'No.SO','Item No', 'UOM'])['Quantity'].sum().reset_index().sort_values(by=['Ext.Doc.No','No.SO', 'Item No']) df['NameFromTaco']=df['Item No'] # print(df) # df['FullName'] = inteminvdf.loc[df['Item No'],'FullName'] @@ -248,14 +248,14 @@ def read_DN_excel(filename): print("Cannot Find Item FullName") listitemNoFullName = df.loc[df['FullName'].isnull()].values.tolist() - df=df.reindex(columns=['Ext.Doc.No.', 'No.SO/Ext.Doc.No.', 'Item No', 'FullName', 'Quantity', 'UOM']) + df=df.reindex(columns=['Ext.Doc.No', 'No.SO', 'Item No', 'FullName', 'Quantity', 'UOM']) # print(df) # print(listitemNoFullName) # print(listitemNoFullName) return False, listitemNoFullName else: - df=df.groupby(['Ext.Doc.No.', 'No.SO/Ext.Doc.No.','Item No', 'UOM', 'FullName'])['Quantity'].sum().reset_index().sort_values(by=['Ext.Doc.No.','No.SO/Ext.Doc.No.', 'Item No']) - df=df.reindex(columns=['Ext.Doc.No.', 'No.SO/Ext.Doc.No.', 'Item No', 'FullName', 'Quantity', 'UOM']) + df=df.groupby(['Ext.Doc.No', 'No.SO','Item No', 'UOM', 'FullName'])['Quantity'].sum().reset_index().sort_values(by=['Ext.Doc.No','No.SO', 'Item No']) + df=df.reindex(columns=['Ext.Doc.No', 'No.SO', 'Item No', 'FullName', 'Quantity', 'UOM']) # print(df) lst = df.to_dict('records') # print(lst) diff --git a/qbpurchaseorderquery.py b/qbpurchaseorderquery.py index 8c14dc4..4be1ef6 100644 --- a/qbpurchaseorderquery.py +++ b/qbpurchaseorderquery.py @@ -342,7 +342,7 @@ class PurchaseOrderQuery: dnlist = self.DN df = pd.DataFrame(dnlist) # print(df) - df['RefNum']= df['No.SO/Ext.Doc.No.'].apply(lambda x: "L"+ x.split("L-")[1]) + df['RefNum']= df['No.SO'].apply(lambda x: "L"+ x.split("L-")[1]) # print(df) ext_doc_no=df['RefNum'].unique().tolist() if len(ext_doc_no)>0: @@ -353,12 +353,12 @@ class PurchaseOrderQuery: print('### PurchaseOrder ###') if __name__ == '__main__': starttime = timeit.default_timer() - # dndict={'DNRefNum': 'G230700127', 'TxnDate': '2023-07-05', 'Memo': 'G230700127', 'lines': [{'Ext.Doc.No.': 'PO0119623070034', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-00666', 'Item No': 'TH-037AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-037AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070045', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-00849', 'Item No': 'TH-037AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-037AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070046', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-00850', 'Item No': 'EDG-805-1/42', 'UOM': 'ROLL', 'FullName': 'TEDG:WG142:EDG-805-1/42', 'Quantity': 3}, {'Ext.Doc.No.': 'PO0119623070046', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-00850', 'Item No': 'EDG-825-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-825-1/22', 'Quantity': 5}, {'Ext.Doc.No.': 'PO0119623070064', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01224', 'Item No': 'TS-W309', 'UOM': 'ROLL_50', 'FullName': 'TSHT:TS DYNAMIX:TS-W309', 'Quantity': 2}, {'Ext.Doc.No.': 'PO0119623070064', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01224', 'Item No': 'TS-W311', 'UOM': 'ROLL_50', 'FullName': 'TSHT:TS DYNAMIX:TS-W311', 'Quantity': 1}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-003D', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-003D', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-009D', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-009D', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-011AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-011AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-014AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-014AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-022AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-022AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-026D', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-026D', 'Quantity': 60}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-036AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-036AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-1205FC', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-1205FC', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-1224FC', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-1224FC', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-131AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-131AA', 'Quantity': 50}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-186AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-186AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-200AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-200AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-202B', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-202B', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-371H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-371H', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-852J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-852J', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070073', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01464', 'Item No': 'TH-906J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-906J', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070088', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01764', 'Item No': 'TV-3024', 'UOM': 'BOX', 'FullName': 'TACH:FLR:TV-3024', 'Quantity': 108}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-001AA', 'UOM': 'PCS', 'FullName': 'TACO:W:TH-001AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-002G', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-002G', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-007G', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-007G', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-013AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-013AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-014G', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-014G', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-022AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-022AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-037AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-037AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-101AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-101AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-102AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-102AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-109AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-109AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-1218FC', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-1218FC', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-200AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-200AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-215AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-215AA', 'Quantity': 45}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-262B', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-262B', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-321H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-321H', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-352H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-352H', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-372H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-372H', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-375H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-375H', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-839J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-839J', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070089', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01792', 'Item No': 'TH-849J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-849J', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070090', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01804', 'Item No': 'EDG-003-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:S122:EDG-003-1/22', 'Quantity': 5}, {'Ext.Doc.No.': 'PO0119623070090', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01804', 'Item No': 'EDG-363-1/42', 'UOM': 'ROLL', 'FullName': 'TEDG:WG142:EDG-363-1/42', 'Quantity': 3}, {'Ext.Doc.No.': 'PO0119623070090', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-01804', 'Item No': 'EDG-806-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-806-1/22', 'Quantity': 5}]} - dndict = {'DNRefNum': 'G230700752', 'TxnDate': '2023-07-15', 'Memo': 'G230700752', 'lines': [{'Ext.Doc.No.': 'PO0119623070242', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-05507', 'Item No': 'TH-040G', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-040G', 'Quantity': 75}, {'Ext.Doc.No.': 'PO0119623070243', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-05510', 'Item No': 'EDG-305-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-305-1/22', 'Quantity': 1}, {'Ext.Doc.No.': 'PO0119623070243', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-05510', 'Item No': 'EDG-373-1/42', 'UOM': 'ROLL', 'FullName': 'TEDG:WG142:EDG-373-1/42', 'Quantity': 3}, {'Ext.Doc.No.': 'PO0119623070259', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-05882', 'Item No': 'TH-007G', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-007G', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070261', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-05899', 'Item No': 'TS-I500', 'UOM': 'ROLL_100', 'FullName': 'TSHT:TS WOODGRAIN:TS-I500', 'Quantity': 1}, {'Ext.Doc.No.': 'PO0119623070261', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-05899', 'Item No': 'TS-P002', 'UOM': 'ROLL_50', 'FullName': 'TSHT:TS SOLID:TS-P002', 'Quantity': 1}, {'Ext.Doc.No.': 'PO0119623070261', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-05899', 'Item No': 'TS-W318', 'UOM': 'ROLL_50', 'FullName': 'TSHT:TS DYNAMIX:TS-W318', 'Quantity': 1}, {'Ext.Doc.No.': 'PO0119623070268', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06052', 'Item No': 'TH-001AA', 'UOM': 'PCS', 'FullName': 'TACO:W:TH-001AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070268', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06052', 'Item No': 'TH-016AA', 'UOM': 'PCS', 'FullName': 'TACO:W:TH-016AA', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070268', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06052', 'Item No': 'TH-119AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-119AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070268', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06052', 'Item No': 'TH-1218FC', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-1218FC', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070268', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06052', 'Item No': 'TH-1236FA', 'UOM': 'PCS', 'FullName': 'TACO:OT:TH-1236FA', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070268', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06052', 'Item No': 'TH-276B', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-276B', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070268', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06052', 'Item No': 'TH-321H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-321H', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070268', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06052', 'Item No': 'TH-357H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-357H', 'Quantity': 45}, {'Ext.Doc.No.': 'PO0119623070268', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06052', 'Item No': 'TH-5013NT', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-5013NT', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070268', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06052', 'Item No': 'TH-845J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-845J', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070269', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06055', 'Item No': 'EDG-003G-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-003G-1/22', 'Quantity': 5}, {'Ext.Doc.No.': 'PO0119623070276', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06190', 'Item No': 'TH-001AA', 'UOM': 'PCS', 'FullName': 'TACO:W:TH-001AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070276', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06190', 'Item No': 'TH-003AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-003AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070276', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06190', 'Item No': 'TH-852J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-852J', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070276', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06190', 'Item No': 'TH-884J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-884J', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070277', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06191', 'Item No': 'EDG-1205-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-1205-1/22', 'Quantity': 5}, {'Ext.Doc.No.': 'PO0119623070277', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06191', 'Item No': 'EDG-275-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-275-1/22', 'Quantity': 5}, {'Ext.Doc.No.': 'PO0119623070277', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06191', 'Item No': 'EDG-371-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-371-1/22', 'Quantity': 5}, {'Ext.Doc.No.': 'PO0119623070277', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06191', 'Item No': 'EDG-909-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-909-1/22', 'Quantity': 2}, {'Ext.Doc.No.': 'PO0119623070284', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06233', 'Item No': 'TA-1100-KB', 'UOM': 'PCS', 'FullName': 'TACH:HWR:TA-1100-KB', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-009AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-009AA', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-016AA', 'UOM': 'PCS', 'FullName': 'TACO:W:TH-016AA', 'Quantity': 45}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-022AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-022AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-025AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-025AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-102AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-102AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-109AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-109AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-1207FC', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-1207FC', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-220AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-220AA', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-325H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-325H', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-357H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-357H', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-362H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-362H', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-371H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-371H', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-817J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-817J', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-825J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-825J', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-861J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-861J', 'Quantity': 30}, {'Ext.Doc.No.': 'PO0119623070285', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06243', 'Item No': 'TH-889FC', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-889FC', 'Quantity': 15}, {'Ext.Doc.No.': 'PO0119623070286', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06244', 'Item No': 'EDG-002-1/42', 'UOM': 'ROLL', 'FullName': 'TEDG:S142:EDG-002-1/42', 'Quantity': 6}, {'Ext.Doc.No.': 'PO0119623070288', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06256', 'Item No': 'EDG-002-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:S122:EDG-002-1/22', 'Quantity': 10}, {'Ext.Doc.No.': 'PO0119623070288', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06256', 'Item No': 'EDG-002G-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-002G-1/22', 'Quantity': 5}, {'Ext.Doc.No.': 'PO0119623070288', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06256', 'Item No': 'EDG-153-1/42', 'UOM': 'ROLL', 'FullName': 'TEDG:WG142:EDG-153-1/42', 'Quantity': 3}, {'Ext.Doc.No.': 'PO0119623070291', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06282', 'Item No': 'TV-3001', 'UOM': 'BOX', 'FullName': 'TACH:FLR:TV-3001', 'Quantity': 41}, {'Ext.Doc.No.': 'PO0119623070295', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06398', 'Item No': 'TH-122AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-122AA', 'Quantity': 2}, {'Ext.Doc.No.': 'PO0119623070298', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06520', 'Item No': 'EDG-003-1/42', 'UOM': 'ROLL', 'FullName': 'TEDG:S142:EDG-003-1/42', 'Quantity': 3}, {'Ext.Doc.No.': 'PO0119623070301', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06533', 'Item No': 'BBS007FE36-450', 'UOM': 'BOX', 'FullName': 'TACH:RLC:BBS007FE36-450', 'Quantity': 1}, {'Ext.Doc.No.': 'PO0119623070301', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06533', 'Item No': 'ET-01/A', 'UOM': 'BOX', 'FullName': 'TACH:HWR:ET-01/A', 'Quantity': 3}, {'Ext.Doc.No.': 'PO0119623070301', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06533', 'Item No': 'ET-01/B', 'UOM': 'BOX', 'FullName': 'TACH:HWR:ET-01/B', 'Quantity': 2}, {'Ext.Doc.No.': 'PO0119623070301', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06533', 'Item No': 'ET-01/C', 'UOM': 'BOX', 'FullName': 'TACH:HWR:ET-01/C', 'Quantity': 2}, {'Ext.Doc.No.': 'POA0119623070006', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06527', 'Item No': 'EDG-153/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG22:EDG-153/22', 'Quantity': 2}, {'Ext.Doc.No.': 'SRTACO23070175', 'No.SO/Ext.Doc.No.': 'TCO-SOL-2307-06091', 'Item No': 'TH-882RE', 'UOM': 'PCS', 'FullName': 'TACO:OT:TH-882RE', 'Quantity': 49}]} + # dndict={'DNRefNum': 'G230700127', 'TxnDate': '2023-07-05', 'Memo': 'G230700127', 'lines': [{'Ext.Doc.No': 'PO0119623070034', 'No.SO': 'TCO-SOL-2307-00666', 'Item No': 'TH-037AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-037AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070045', 'No.SO': 'TCO-SOL-2307-00849', 'Item No': 'TH-037AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-037AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070046', 'No.SO': 'TCO-SOL-2307-00850', 'Item No': 'EDG-805-1/42', 'UOM': 'ROLL', 'FullName': 'TEDG:WG142:EDG-805-1/42', 'Quantity': 3}, {'Ext.Doc.No': 'PO0119623070046', 'No.SO': 'TCO-SOL-2307-00850', 'Item No': 'EDG-825-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-825-1/22', 'Quantity': 5}, {'Ext.Doc.No': 'PO0119623070064', 'No.SO': 'TCO-SOL-2307-01224', 'Item No': 'TS-W309', 'UOM': 'ROLL_50', 'FullName': 'TSHT:TS DYNAMIX:TS-W309', 'Quantity': 2}, {'Ext.Doc.No': 'PO0119623070064', 'No.SO': 'TCO-SOL-2307-01224', 'Item No': 'TS-W311', 'UOM': 'ROLL_50', 'FullName': 'TSHT:TS DYNAMIX:TS-W311', 'Quantity': 1}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-003D', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-003D', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-009D', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-009D', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-011AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-011AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-014AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-014AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-022AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-022AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-026D', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-026D', 'Quantity': 60}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-036AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-036AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-1205FC', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-1205FC', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-1224FC', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-1224FC', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-131AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-131AA', 'Quantity': 50}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-186AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-186AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-200AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-200AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-202B', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-202B', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-371H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-371H', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-852J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-852J', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070073', 'No.SO': 'TCO-SOL-2307-01464', 'Item No': 'TH-906J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-906J', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070088', 'No.SO': 'TCO-SOL-2307-01764', 'Item No': 'TV-3024', 'UOM': 'BOX', 'FullName': 'TACH:FLR:TV-3024', 'Quantity': 108}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-001AA', 'UOM': 'PCS', 'FullName': 'TACO:W:TH-001AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-002G', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-002G', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-007G', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-007G', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-013AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-013AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-014G', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-014G', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-022AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-022AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-037AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-037AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-101AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-101AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-102AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-102AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-109AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-109AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-1218FC', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-1218FC', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-200AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-200AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-215AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-215AA', 'Quantity': 45}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-262B', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-262B', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-321H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-321H', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-352H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-352H', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-372H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-372H', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-375H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-375H', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-839J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-839J', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070089', 'No.SO': 'TCO-SOL-2307-01792', 'Item No': 'TH-849J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-849J', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070090', 'No.SO': 'TCO-SOL-2307-01804', 'Item No': 'EDG-003-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:S122:EDG-003-1/22', 'Quantity': 5}, {'Ext.Doc.No': 'PO0119623070090', 'No.SO': 'TCO-SOL-2307-01804', 'Item No': 'EDG-363-1/42', 'UOM': 'ROLL', 'FullName': 'TEDG:WG142:EDG-363-1/42', 'Quantity': 3}, {'Ext.Doc.No': 'PO0119623070090', 'No.SO': 'TCO-SOL-2307-01804', 'Item No': 'EDG-806-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-806-1/22', 'Quantity': 5}]} + dndict = {'DNRefNum': 'G230700752', 'TxnDate': '2023-07-15', 'Memo': 'G230700752', 'lines': [{'Ext.Doc.No': 'PO0119623070242', 'No.SO': 'TCO-SOL-2307-05507', 'Item No': 'TH-040G', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-040G', 'Quantity': 75}, {'Ext.Doc.No': 'PO0119623070243', 'No.SO': 'TCO-SOL-2307-05510', 'Item No': 'EDG-305-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-305-1/22', 'Quantity': 1}, {'Ext.Doc.No': 'PO0119623070243', 'No.SO': 'TCO-SOL-2307-05510', 'Item No': 'EDG-373-1/42', 'UOM': 'ROLL', 'FullName': 'TEDG:WG142:EDG-373-1/42', 'Quantity': 3}, {'Ext.Doc.No': 'PO0119623070259', 'No.SO': 'TCO-SOL-2307-05882', 'Item No': 'TH-007G', 'UOM': 'PCS', 'FullName': 'TACO:G_D:TH-007G', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070261', 'No.SO': 'TCO-SOL-2307-05899', 'Item No': 'TS-I500', 'UOM': 'ROLL_100', 'FullName': 'TSHT:TS WOODGRAIN:TS-I500', 'Quantity': 1}, {'Ext.Doc.No': 'PO0119623070261', 'No.SO': 'TCO-SOL-2307-05899', 'Item No': 'TS-P002', 'UOM': 'ROLL_50', 'FullName': 'TSHT:TS SOLID:TS-P002', 'Quantity': 1}, {'Ext.Doc.No': 'PO0119623070261', 'No.SO': 'TCO-SOL-2307-05899', 'Item No': 'TS-W318', 'UOM': 'ROLL_50', 'FullName': 'TSHT:TS DYNAMIX:TS-W318', 'Quantity': 1}, {'Ext.Doc.No': 'PO0119623070268', 'No.SO': 'TCO-SOL-2307-06052', 'Item No': 'TH-001AA', 'UOM': 'PCS', 'FullName': 'TACO:W:TH-001AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070268', 'No.SO': 'TCO-SOL-2307-06052', 'Item No': 'TH-016AA', 'UOM': 'PCS', 'FullName': 'TACO:W:TH-016AA', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070268', 'No.SO': 'TCO-SOL-2307-06052', 'Item No': 'TH-119AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-119AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070268', 'No.SO': 'TCO-SOL-2307-06052', 'Item No': 'TH-1218FC', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-1218FC', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070268', 'No.SO': 'TCO-SOL-2307-06052', 'Item No': 'TH-1236FA', 'UOM': 'PCS', 'FullName': 'TACO:OT:TH-1236FA', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070268', 'No.SO': 'TCO-SOL-2307-06052', 'Item No': 'TH-276B', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-276B', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070268', 'No.SO': 'TCO-SOL-2307-06052', 'Item No': 'TH-321H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-321H', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070268', 'No.SO': 'TCO-SOL-2307-06052', 'Item No': 'TH-357H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-357H', 'Quantity': 45}, {'Ext.Doc.No': 'PO0119623070268', 'No.SO': 'TCO-SOL-2307-06052', 'Item No': 'TH-5013NT', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-5013NT', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070268', 'No.SO': 'TCO-SOL-2307-06052', 'Item No': 'TH-845J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-845J', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070269', 'No.SO': 'TCO-SOL-2307-06055', 'Item No': 'EDG-003G-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-003G-1/22', 'Quantity': 5}, {'Ext.Doc.No': 'PO0119623070276', 'No.SO': 'TCO-SOL-2307-06190', 'Item No': 'TH-001AA', 'UOM': 'PCS', 'FullName': 'TACO:W:TH-001AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070276', 'No.SO': 'TCO-SOL-2307-06190', 'Item No': 'TH-003AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-003AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070276', 'No.SO': 'TCO-SOL-2307-06190', 'Item No': 'TH-852J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-852J', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070276', 'No.SO': 'TCO-SOL-2307-06190', 'Item No': 'TH-884J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-884J', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070277', 'No.SO': 'TCO-SOL-2307-06191', 'Item No': 'EDG-1205-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-1205-1/22', 'Quantity': 5}, {'Ext.Doc.No': 'PO0119623070277', 'No.SO': 'TCO-SOL-2307-06191', 'Item No': 'EDG-275-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-275-1/22', 'Quantity': 5}, {'Ext.Doc.No': 'PO0119623070277', 'No.SO': 'TCO-SOL-2307-06191', 'Item No': 'EDG-371-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-371-1/22', 'Quantity': 5}, {'Ext.Doc.No': 'PO0119623070277', 'No.SO': 'TCO-SOL-2307-06191', 'Item No': 'EDG-909-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-909-1/22', 'Quantity': 2}, {'Ext.Doc.No': 'PO0119623070284', 'No.SO': 'TCO-SOL-2307-06233', 'Item No': 'TA-1100-KB', 'UOM': 'PCS', 'FullName': 'TACH:HWR:TA-1100-KB', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-009AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-009AA', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-016AA', 'UOM': 'PCS', 'FullName': 'TACO:W:TH-016AA', 'Quantity': 45}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-022AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-022AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-025AA', 'UOM': 'PCS', 'FullName': 'TACO:AA:TH-025AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-102AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-102AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-109AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-109AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-1207FC', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-1207FC', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-220AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-220AA', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-325H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-325H', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-357H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-357H', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-362H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-362H', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-371H', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-371H', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-817J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-817J', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-825J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-825J', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-861J', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-861J', 'Quantity': 30}, {'Ext.Doc.No': 'PO0119623070285', 'No.SO': 'TCO-SOL-2307-06243', 'Item No': 'TH-889FC', 'UOM': 'PCS', 'FullName': 'TACO:J_FC:TH-889FC', 'Quantity': 15}, {'Ext.Doc.No': 'PO0119623070286', 'No.SO': 'TCO-SOL-2307-06244', 'Item No': 'EDG-002-1/42', 'UOM': 'ROLL', 'FullName': 'TEDG:S142:EDG-002-1/42', 'Quantity': 6}, {'Ext.Doc.No': 'PO0119623070288', 'No.SO': 'TCO-SOL-2307-06256', 'Item No': 'EDG-002-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:S122:EDG-002-1/22', 'Quantity': 10}, {'Ext.Doc.No': 'PO0119623070288', 'No.SO': 'TCO-SOL-2307-06256', 'Item No': 'EDG-002G-1/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG122:EDG-002G-1/22', 'Quantity': 5}, {'Ext.Doc.No': 'PO0119623070288', 'No.SO': 'TCO-SOL-2307-06256', 'Item No': 'EDG-153-1/42', 'UOM': 'ROLL', 'FullName': 'TEDG:WG142:EDG-153-1/42', 'Quantity': 3}, {'Ext.Doc.No': 'PO0119623070291', 'No.SO': 'TCO-SOL-2307-06282', 'Item No': 'TV-3001', 'UOM': 'BOX', 'FullName': 'TACH:FLR:TV-3001', 'Quantity': 41}, {'Ext.Doc.No': 'PO0119623070295', 'No.SO': 'TCO-SOL-2307-06398', 'Item No': 'TH-122AA', 'UOM': 'PCS', 'FullName': 'TACO:AA_B_H:TH-122AA', 'Quantity': 2}, {'Ext.Doc.No': 'PO0119623070298', 'No.SO': 'TCO-SOL-2307-06520', 'Item No': 'EDG-003-1/42', 'UOM': 'ROLL', 'FullName': 'TEDG:S142:EDG-003-1/42', 'Quantity': 3}, {'Ext.Doc.No': 'PO0119623070301', 'No.SO': 'TCO-SOL-2307-06533', 'Item No': 'BBS007FE36-450', 'UOM': 'BOX', 'FullName': 'TACH:RLC:BBS007FE36-450', 'Quantity': 1}, {'Ext.Doc.No': 'PO0119623070301', 'No.SO': 'TCO-SOL-2307-06533', 'Item No': 'ET-01/A', 'UOM': 'BOX', 'FullName': 'TACH:HWR:ET-01/A', 'Quantity': 3}, {'Ext.Doc.No': 'PO0119623070301', 'No.SO': 'TCO-SOL-2307-06533', 'Item No': 'ET-01/B', 'UOM': 'BOX', 'FullName': 'TACH:HWR:ET-01/B', 'Quantity': 2}, {'Ext.Doc.No': 'PO0119623070301', 'No.SO': 'TCO-SOL-2307-06533', 'Item No': 'ET-01/C', 'UOM': 'BOX', 'FullName': 'TACH:HWR:ET-01/C', 'Quantity': 2}, {'Ext.Doc.No': 'POA0119623070006', 'No.SO': 'TCO-SOL-2307-06527', 'Item No': 'EDG-153/22', 'UOM': 'ROLL', 'FullName': 'TEDG:WG22:EDG-153/22', 'Quantity': 2}, {'Ext.Doc.No': 'SRTACO23070175', 'No.SO': 'TCO-SOL-2307-06091', 'Item No': 'TH-882RE', 'UOM': 'PCS', 'FullName': 'TACO:OT:TH-882RE', 'Quantity': 49}]} dnlist = dndict['lines'] df = pd.DataFrame(dnlist) # print(df) - df['RefNum']= df['No.SO/Ext.Doc.No.'].apply(lambda x: "L"+ x.split("L-")[1]) + df['RefNum']= df['No.SO'].apply(lambda x: "L"+ x.split("L-")[1]) # print(df) ext_doc_no=df['RefNum'].unique().tolist() From 9e65890d0f68bc9424d661d53a449029ca0281e8 Mon Sep 17 00:00:00 2001 From: bcomsugi Date: Fri, 29 Dec 2023 04:41:31 +0700 Subject: [PATCH 15/27] save inv --- SO_to_Inv/readSO.py | 74 ++++-- .../templates/Invoice/so_details_form.html | 104 +++++++++ .../templates/Invoice/so_list_form.html | 2 +- django/Invoice/urls.py | 3 +- django/Invoice/views.py | 216 +++++++++++++++++- records | 1 + 6 files changed, 363 insertions(+), 37 deletions(-) create mode 100644 django/Invoice/templates/Invoice/so_details_form.html create mode 100644 records diff --git a/SO_to_Inv/readSO.py b/SO_to_Inv/readSO.py index ee31368..1b4b9dd 100644 --- a/SO_to_Inv/readSO.py +++ b/SO_to_Inv/readSO.py @@ -25,6 +25,7 @@ class SalesOrderQuery: self._df_price_level = pd.read_excel(os.path.join(self.cwd, self.item_inventory_path, self.price_level_filename), usecols=['FullName', 'PriceLevelName', 'CustomPrice'],) print(self._df_price_level) print(type(self._df_price_level.loc[(self._df_price_level['FullName']=="ECO:0:ECO-002") & (self._df_price_level['PriceLevelName']=="T 202202")].values.tolist()[0][2])) + print(self._df_price_level.loc[(self._df_price_level['FullName']=="TEDG:S122:EDG-009-1/22") & (self._df_price_level['PriceLevelName']=="T 202202")].values.tolist()[0][2]) self.FullName = kwargs['FullName'] if 'FullName' in kwargs else None self.CustomerPriceLevelName_filename = "CustomerList.xlsx" @@ -33,8 +34,9 @@ class SalesOrderQuery: print(self._df_customer) self.Customer = None if self.FullName: - self.Customer = self._df_customer.loc[(self._df_customer["FullName"]==self.FullName)].values.tolist()[0] - print(f'Customer:{self.Customer}') + if self.FullName in self._df_customer['FullName'].values: + self.Customer = self._df_customer.loc[(self._df_customer["FullName"]==self.FullName)].values.tolist()[0] + print(f'Customer:{self.Customer}') self.DN = kwargs['DN'] if 'DN' in kwargs else {} self.Reuse = kwargs['Reuse'] if 'Reuse' in kwargs else None @@ -176,8 +178,11 @@ class SalesOrderQuery: return self.get_customer_pricelevel(response_string) return response_string - def create_invoiceadd_QBXML(self): + def create_invoiceadd_QBXML(self, soList=None): + print('create_ionvoiceadd_QBXML') + if soList: + self.SalesOrderList = soList root = ET.Element("QBXML") root.tail = "\n" root.text = "\n " @@ -225,12 +230,12 @@ class SalesOrderQuery: # ItemFullName = self.create_sub_element(ET, ItemRef, "FullName", "400_Sales Discount", 12) # ItemRate = self.create_sub_element(ET, InvoiceLineAdd, "Rate", str(disc_amount), 10) - if disc_amount != 0: - # disc_amount=format(disc_amount, ".2f") - InvoiceLineAdd = self.create_sub_element(ET, InvoiceAdd, "InvoiceLineAdd", "\n ", 10 ) - ItemRef = self.create_sub_element(ET, InvoiceLineAdd, "ItemRef", "\n ", 12) - ItemFullName = self.create_sub_element(ET, ItemRef, "FullName", "400_Sales Discount", 12) - ItemRate = self.create_sub_element(ET, InvoiceLineAdd, "Rate", str(disc_amount), 10) + if salesorder['Disc_Amount']!=0: # disc_amount != 0: + # disc_amount=format(disc_amount, ".2f") + InvoiceLineAdd = self.create_sub_element(ET, InvoiceAdd, "InvoiceLineAdd", "\n ", 10 ) + ItemRef = self.create_sub_element(ET, InvoiceLineAdd, "ItemRef", "\n ", 12) + ItemFullName = self.create_sub_element(ET, ItemRef, "FullName", "400_Sales Discount", 12) + ItemRate = self.create_sub_element(ET, InvoiceLineAdd, "Rate", str(disc_amount), 10) mydata = ET.tostring(root, encoding = "unicode") @@ -293,10 +298,22 @@ class SalesOrderQuery: else: return False, status_code + def get_discperpcs(self, ItemFullName, Rate:float): + discPerPcs = 0 + if self.Customer: + if self.Customer[2]: + pricelist = self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2] + discPerPcs = Rate-pricelist + # ic(Rate, disc, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.SPPriceLevelName)].values.tolist()[0][2])) + if discPerPcs < 0 : + discPerPcs = 0 + print(f"WARNING: Rate is Lower than Pricelist Cust:{self.Customer} ItemName:{ItemFullName} Rate:{Rate} < {pricelist}") + return discPerPcs - def _get_sales_order_header(self, response_string): + + def _get_sales_order_header(self, response_string, includefullInvoiced=False): print('_get_sales_order_header') - print(f'responsestring:{self.pprintXml(response_string)}') + # print(f'responsestring:{self.pprintXml(response_string)}') QBXML = ET.fromstring(response_string) datadict = {} SalesOrderdict = {} @@ -319,14 +336,19 @@ class SalesOrderQuery: TotalAmount = SalesOrderRet.find('TotalAmount').text IsFullyInvoiced = SalesOrderRet.find('IsFullyInvoiced').text IsManuallyClosed = SalesOrderRet.find('IsManuallyClosed').text + if includefullInvoiced==False: + if IsFullyInvoiced.lower()=='true': + # print(IsFullyInvoiced) + continue # print(CustomerFullName, TxnID, TotalAmount) SalesOrderdict = {'RefNumber':RefNumber, 'CustomerFullName':CustomerFullName, 'TxnID':TxnID, 'TxnDate':TxnDate, 'TxnNumber':TxnNumber, 'TotalAmount':TotalAmount, 'IsFullyInvoiced':IsFullyInvoiced, 'IsManuallyClosed':IsManuallyClosed, 'SalesOrderLineRet':[]} SalesOrderLineRet = SalesOrderRet.findall('SalesOrderLineRet') # ic(len(SalesOrderLineRet)) + disc_amount=0 if len(SalesOrderLineRet) > 0: - disc_amount=0 + # disc_amount=0 for SalesOrderLineRet in SalesOrderLineRet: discPerItem = 0 discPerPcs = 0 @@ -353,17 +375,20 @@ class SalesOrderQuery: BackOrdered = float(Quantity) - float(Invoiced) if BackOrdered > 0 and LineIsManuallyClosed.lower() == 'false' : # ic(self.Customer) - if self.Customer: - if self.Customer[2]: - discPerPcs = Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2] - # ic(Rate, disc, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.SPPriceLevelName)].values.tolist()[0][2])) - if discPerPcs > 0: - print(Quantity, BackOrdered, Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2])) - discPerItem = BackOrdered * discPerPcs - disc_amount += discPerItem - # disc_amount += BackOrdered * discPerPcs # (Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) - else: - discPerPcs = 0 + discPerPcs = self.get_discperpcs(ItemFullName, Rate) + discPerItem = BackOrdered * discPerPcs + disc_amount += discPerItem + # if self.Customer: + # if self.Customer[2]: + # discPerPcs = Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2] + # # ic(Rate, disc, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.SPPriceLevelName)].values.tolist()[0][2])) + # if discPerPcs > 0: + # print(Quantity, BackOrdered, Rate, (Rate - self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2])) + # discPerItem = BackOrdered * discPerPcs + # disc_amount += discPerItem + # # disc_amount += BackOrdered * discPerPcs # (Rate-self._df_price_level.loc[(self._df_price_level['FullName']==ItemFullName) & (self._df_price_level['PriceLevelName']==self.Customer[2])].values.tolist()[0][2]) + # else: + # discPerPcs = 0 SalesOrderLinedict = {'TxnLineID':TxnLineID, 'ItemFullName':ItemFullName, 'Quantity':Quantity, @@ -567,11 +592,12 @@ class SalesOrderQuery: print(f'txnid: {txnlist}', type(txnlist)) txnid = [] for x in txnlist: + # print(x, type(x)) if isinstance(x, list): txnid.append(x[0]) else: txnid.append(x) - break + # break # txnid = [x[0] if isinstance(x, list) else x for x in txnid ] print(txnid) if txnid: diff --git a/django/Invoice/templates/Invoice/so_details_form.html b/django/Invoice/templates/Invoice/so_details_form.html new file mode 100644 index 0000000..0a276fc --- /dev/null +++ b/django/Invoice/templates/Invoice/so_details_form.html @@ -0,0 +1,104 @@ +{% extends 'base.html' %} +{% block body %} + +
+ +
+{% endblock %} \ No newline at end of file diff --git a/django/Invoice/templates/Invoice/so_list_form.html b/django/Invoice/templates/Invoice/so_list_form.html index 2b6137a..7e28919 100644 --- a/django/Invoice/templates/Invoice/so_list_form.html +++ b/django/Invoice/templates/Invoice/so_list_form.html @@ -2,7 +2,7 @@ {% block body %}
-
+ {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} {% block body %}{% endblock body %} From abc64aa7a08ac39e2973a8b798ce277e22ed2729 Mon Sep 17 00:00:00 2001 From: bcomsugi Date: Sun, 31 Dec 2023 03:42:00 +0700 Subject: [PATCH 18/27] messages fixed --- .../templates/Invoice/show-customers.html | 15 ++-------- .../templates/Invoice/so_details_form.html | 4 ++- .../templates/Invoice/so_list_form.html | 2 +- django/Invoice/views.py | 15 ++++++---- django/templates/base.html | 30 ++++++++++--------- 5 files changed, 32 insertions(+), 34 deletions(-) diff --git a/django/Invoice/templates/Invoice/show-customers.html b/django/Invoice/templates/Invoice/show-customers.html index 62379c1..ea66135 100644 --- a/django/Invoice/templates/Invoice/show-customers.html +++ b/django/Invoice/templates/Invoice/show-customers.html @@ -4,18 +4,7 @@ {% block title %}Invoice{% endblock title %} {% block body %} - {% comment %} {% if messages %} - - {% endif %} {% endcomment %} - {% if messages %} -
    - {% for message in messages %} - {{ message }} - {% endfor %} -
- {% endif %} +
@@ -23,7 +12,7 @@
- + diff --git a/django/Invoice/templates/Invoice/so_details_form.html b/django/Invoice/templates/Invoice/so_details_form.html index e06d20b..3f7955b 100644 --- a/django/Invoice/templates/Invoice/so_details_form.html +++ b/django/Invoice/templates/Invoice/so_details_form.html @@ -5,11 +5,13 @@ {% csrf_token %}