diff --git a/SO_to_Inv/readSO.py b/SO_to_Inv/readSO.py
index 555cdda..49ef292 100644
--- a/SO_to_Inv/readSO.py
+++ b/SO_to_Inv/readSO.py
@@ -9,7 +9,7 @@ import timeit
import os
import pythoncom
# from icecream import ic
-
+from decimal import Decimal
# ic.configureOutput(includeContext=True, )
class SalesOrderQuery:
@@ -204,6 +204,7 @@ class SalesOrderQuery:
# Memo = self.create_sub_element(ET, InvoiceAdd, "Memo", self.DN['Memo'], 10 )
disc_amount = 0
for soidx, salesorder in enumerate(self.SalesOrderList):
+ disc_amount = 0
if 'TxnID' in salesorder:
SOTxnId = salesorder['TxnID']
# disc_amount+=int(salesorder['Disc_Amount'])
@@ -254,8 +255,8 @@ class SalesOrderQuery:
# print(f"replyfrom qbxml:{self.connect_to_quickbooks(qbxml_query)}")
# print([s for s in qbxml_query.split('\n') if s.strip(' ') != ''])
- print(self.pprintXml(qbxml_query))
- return qbxml_query
+ # print(self.pprintXml(qbxml_query))
+ return self.pprintXml(qbxml_query)
def connect_to_quickbooks(self, qbxml_query):
@@ -306,7 +307,7 @@ class SalesOrderQuery:
else:
return False, status_code
- def get_discperpcs(self, ItemFullName, Rate:float):
+ def get_discperpcs(self, ItemFullName, Rate):
discPerPcs = 0
if self.Customer:
if self.Customer[2]:
@@ -321,7 +322,7 @@ class SalesOrderQuery:
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 sales order header:{self.pprintXml(response_string)}')
QBXML = ET.fromstring(response_string)
datadict = {}
SalesOrderdict = {}
@@ -360,27 +361,36 @@ class SalesOrderQuery:
for SalesOrderLineRet in SalesOrderLineRet:
discPerItem = 0
discPerPcs = 0
+ convertQTY = 1
TxnLineID = SalesOrderLineRet.find('TxnLineID').text
ItemFullName = SalesOrderLineRet.find('ItemRef/FullName')
if ItemFullName is None:
print("no itemfullname")
- break
+ continue
else:
ItemFullName=ItemFullName.text
# print(ItemFullName)
Quantity = SalesOrderLineRet.find('Quantity').text
UnitOfMeasure = SalesOrderLineRet.find('UnitOfMeasure').text
+
+ ### modified if UOM has ConvertQTY: '_' or ' of '-> in OverrideUOMSetRef
+ if '_' in UnitOfMeasure:
+ convertQTY = int(UnitOfMeasure.split('_')[1])
OverrideUOMSetRef = SalesOrderLineRet.find('OverrideUOMSetRef/FullName')
if OverrideUOMSetRef != None:
OverrideUOMSetRef = OverrideUOMSetRef.text
- Rate = float(SalesOrderLineRet.find('Rate').text)
+ if 'of' in OverrideUOMSetRef and UnitOfMeasure.upper() == 'BOX':
+ convertQTY = int(OverrideUOMSetRef.split('of')[1])
+ print(f'OverrideUOMSetRef:{OverrideUOMSetRef}')
+ ###
- Amount = float(SalesOrderLineRet.find('Amount').text)
+ Rate = Decimal(SalesOrderLineRet.find('Rate').text)
+ Amount = Decimal(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)
+ BackOrdered = Decimal(Quantity) - Decimal(Invoiced)
if BackOrdered > 0 and LineIsManuallyClosed.lower() == 'false' :
# ic(self.Customer)
discPerPcs = self.get_discperpcs(ItemFullName, Rate)
@@ -408,6 +418,7 @@ class SalesOrderQuery:
'LineIsManuallyClosed':LineIsManuallyClosed,
'discPerItem':discPerItem, # backorder qty * disc per pcs
'discPerPcs':discPerPcs,
+ 'convertQTY':convertQTY,
}
SalesOrderdict['SalesOrderLineRet'].append(SalesOrderLinedict)
SalesOrderdict['Disc_Amount']=disc_amount
diff --git a/django/Invoice/templates/Invoice/so_details_form.html b/django/Invoice/templates/Invoice/so_details_form.html
index 0a276fc..e06d20b 100644
--- a/django/Invoice/templates/Invoice/so_details_form.html
+++ b/django/Invoice/templates/Invoice/so_details_form.html
@@ -26,12 +26,8 @@
{% for so_dict in objects %}
- {{so_dict}}
-
- {{so_dict.RefNumber}}
+
{% for so_line in so_dict.SalesOrderLineRet %}
- {{so_dict.RefNumber}}
- {{so_line.ItemFullName}}
|
@@ -43,18 +39,18 @@
{% endfor %}
-
+
|
{{ so_dict.TxnDate }} |
{{ so_dict.RefNumber }} |
- {{ so_line.Quantity }} |
- {{ so_line.Invoiced }} |
- |
+ {% widthratio so_line.Quantity so_line.convertQTY 1 %} |
+ {% widthratio so_line.Invoiced so_line.convertQTY 1 %} |
+ |
{{ so_line.UOM }} |
- |
+ |
{% endfor %}
{% endfor %}
diff --git a/django/Invoice/views.py b/django/Invoice/views.py
index f494b01..8540818 100644
--- a/django/Invoice/views.py
+++ b/django/Invoice/views.py
@@ -15,6 +15,7 @@ import os
import pandas as pd
from django.conf import settings
from icecream import ic
+from decimal import Decimal
ic.configureOutput(includeContext= True)
@@ -197,21 +198,40 @@ def save_inv(request):
del data['other_rate']
print(f'others:{others}')
- # print(f"datadict:{data}")
+ print(f"datadict:{data}")
+ required_data = ['RefNumber', 'CustomerFullName', 'TxnID', 'TxnDate', 'TotalAmount', 'TxnLineID', 'ItemFullName',
+ 'Quantity', 'UOM', 'Rate', 'Amount', 'Invoiced', 'LineIsManuallyClosed', 'backordered', 'rate', 'convertQTY']
+ if 'so_field' not in data:
+ return HttpResponse("no Selected Items. Please select at least 1 item to be invoiced.")
+ for _ in required_data:
+ if _ not in data:
+ return HttpResponse(f"Required data not returned from the form: {_}")
+
+ ### retrieve only the selected so_field ###
+ so_field = data['so_field']
+ del data['so_field']
+ selectedItems = []
+ for _ in so_field:
+ if _ not in data['TxnLineID']:
+ return HttpResponse(f"One of the TxnLineID is not valid: {_}")
+ data_idx = data['TxnLineID'].index(_)
try:
df = pd.DataFrame(data)
print(df)
+ df = df[df['TxnLineID'].isin(so_field)].reset_index()
+ print(df)
except:
print(Exception)
return HttpResponse("DataFrame Error")
# print(f'json:{df.to_json(orient="records")}')
web_dict = df.to_dict("records")
# print(f'web_dict:{web_dict}' )
- web_dict = sorted(web_dict, key=lambda x: x['TxnLineID'])
+ web_dict = sorted(web_dict, key=lambda x: x['TxnID'])
# print(f'Sorted web_dict:{web_dict}' )
if ('so_field' in request.POST) and ('customer_fullname' in request.POST):
print(request.POST.getlist('so_field'))
- open_sales_orders_TxnID = unique(request.POST.getlist('so_field'))
+ # open_sales_orders_TxnID = unique(request.POST.getlist('so_field'))
+ open_sales_orders_TxnID = unique(df['TxnID'].to_list())
customer_fullname = request.POST.get('customer_fullname')
print(f'Customer_fullname:{customer_fullname} -> request values:{open_sales_orders_TxnID}')
### get the SO detail
@@ -246,28 +266,34 @@ def save_inv(request):
for tu_line_ret in tu_['SalesOrderLineRet']:
# print(tu_line_ret)
if web['TxnLineID']==tu_line_ret['TxnLineID'] and web['ItemFullName']==tu_line_ret['ItemFullName']:
- if 0 < float(web['backordered']) <= float(tu_line_ret['BackOrdered']):
+ ### modified back the rate and backordered using convertQTY ###
+ convertQTY = int(tu_line_ret['convertQTY'])
+ webbackordered = Decimal(web['backordered']) * convertQTY
+ webrate = Decimal(web['rate']) / convertQTY
+ ###
+ if 0 < webbackordered <= Decimal(tu_line_ret['BackOrdered']):
# print('put in list')
discPerPcs=0
discPerItem=0
- if float(web['rate']) == float(tu_line_ret['Rate']):
- discPerPcs = ini.get_discperpcs(web['ItemFullName'], float(web['rate']))
- elif float(web['rate']) < float(tu_line_ret['Rate']):
- discPerPcs = float(tu_line_ret['Rate']) - float(web['rate'])
- discPerItem = float(web['backordered']) * discPerPcs
+ if webrate == Decimal(tu_line_ret['Rate']):
+ discPerPcs = ini.get_discperpcs(web['ItemFullName'], webrate)
+ elif webrate < Decimal(tu_line_ret['Rate']):
+ discPerPcs = Decimal(tu_line_ret['Rate']) - webrate
+ discPerItem = webbackordered * discPerPcs
disc_amount += discPerItem
SalesOrderLinedict = {'TxnLineID':web['TxnLineID'],
- 'ItemFullName':web['ItemFullName'],
+ 'ItemFullName':tu_line_ret['ItemFullName'],
'Quantity':tu_line_ret['Quantity'],
'UOM':tu_line_ret['UOM'],
- 'Rate':float(web['rate']),
- 'Amount':float(tu_line_ret['Amount']),
- 'BackOrdered':float(web['backordered']),
+ 'Rate':webrate,
+ 'Amount':Decimal(tu_line_ret['Amount']),
+ 'BackOrdered':webbackordered,
'Invoiced':tu_line_ret['Invoiced'],
'LineIsManuallyClosed':tu_line_ret['LineIsManuallyClosed'],
'discPerItem':discPerItem, # backorder qty * disc per pcs
'discPerPcs':discPerPcs,
+ 'convertQTY':tu_line_ret['convertQTY']
}
# print(f'salesorderlineddict:{SalesOrderLinedict}')
_salesorderlineret = dict_['SalesOrderLineRet']
@@ -277,7 +303,11 @@ def save_inv(request):
break
break
print(f'last:{dict_}')
- if dict_ != data_to_save[-1]: #append the last dict_
+ print(f'datatosaveonly:{data_to_save}')
+ if not data_to_save:
+ dict_['Disc_Amount']=disc_amount
+ data_to_save.append(dict_)
+ elif dict_ != data_to_save[-1]: #append the last dict_
dict_['Disc_Amount']=disc_amount
data_to_save.append(dict_)
print('save the last dict')
@@ -296,9 +326,14 @@ def save_inv(request):
print(invoiceaddQBXML)
result=None
- result = ini.connect_to_quickbooks(ini.create_invoiceadd_QBXML())
+ # result = ini.connect_to_quickbooks(ini.create_invoiceadd_QBXML())
print("RESULT:")
print(result)
+ if result and ini.status_ok(result):
+ pass
+
+ messages.success(request, 'Invoice Has Been SAVED')
+ return redirect('Invoice:show_customer')
return render(request, "Invoice/so_details_form.html", context)
else:
return HttpResponse(f"You cannot Save, because There Is No Open Sales Order for Customer: {customer_fullname}")
diff --git a/django/templates/base.html b/django/templates/base.html
index dc46c24..4b510de 100644
--- a/django/templates/base.html
+++ b/django/templates/base.html
@@ -6,8 +6,8 @@
- {% comment %}
- {% endcomment %}
+
+
@@ -83,6 +83,17 @@
+ {% if messages %}
+ {% for message in messages %}
+
+ {{ message | safe }}
+
+
+
+ {% endfor %}
+ {% endif %}
{% block body %}{% endblock body %}