mirror of
https://github.com/bcomsugi/dasaproject.git
synced 2026-01-10 06:52:36 +07:00
saved
This commit is contained in:
parent
56594e963a
commit
67ab69750d
@ -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
|
||||
|
||||
@ -26,12 +26,8 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for so_dict in objects %}
|
||||
{{so_dict}}
|
||||
|
||||
{{so_dict.RefNumber}}
|
||||
<!-- {{so_dict}} -->
|
||||
{% for so_line in so_dict.SalesOrderLineRet %}
|
||||
{{so_dict.RefNumber}}
|
||||
{{so_line.ItemFullName}}
|
||||
<tr>
|
||||
<td>
|
||||
<input type="hidden" name="RefNumber" value="{{ so_dict.RefNumber }}">
|
||||
@ -43,18 +39,18 @@
|
||||
<input type="hidden" name="{{ k }}" value="{{ v }}">
|
||||
{% endfor %}
|
||||
<div class="form-check">
|
||||
<input type="checkbox" name="so_field" value="{{ so_dict.TxnID }}" id="id_so_field_{{forloop.counter}}" class="form-check-input" checked>
|
||||
<input type="checkbox" name="so_field" value="{{ so_line.TxnLineID }}" id="id_so_field_{{forloop.counter}}" class="form-check-input" checked>
|
||||
<label for="id_so_field_{{ forloop.counter }}" class="form-check-label">{{so_line.ItemFullName}}
|
||||
</label>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ so_dict.TxnDate }}</td>
|
||||
<td>{{ so_dict.RefNumber }}</td>
|
||||
<td>{{ so_line.Quantity }}</td>
|
||||
<td>{{ so_line.Invoiced }}</td>
|
||||
<td><input type="number" name="backordered" required value="{{ so_line.BackOrdered }}" min="0" max="{{ so_line.BackOrdered }}"> </td>
|
||||
<td>{% widthratio so_line.Quantity so_line.convertQTY 1 %}</td>
|
||||
<td>{% widthratio so_line.Invoiced so_line.convertQTY 1 %}</td>
|
||||
<td><input type="number" name="backordered" required value="{% widthratio so_line.BackOrdered so_line.convertQTY 1 %}" min="0" max="{% widthratio so_line.BackOrdered so_line.convertQTY 1 %}"> </td>
|
||||
<td>{{ so_line.UOM }}</td>
|
||||
<td><input type="number" name="rate" required value="{{ so_line.Rate }}" min="0" > </td>
|
||||
<td><input type="number" name="rate" required value="{% widthratio so_line.Rate 1 so_line.convertQTY %}" min="0" > </td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
@ -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}")
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
{% comment %} <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script> {% endcomment %}
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
|
||||
<link href= {% static 'bootstrap.min.css' %} rel="stylesheet" crossorigin="anonymous">
|
||||
<script src= {% static 'bootstrap.bundle.min.js' %} ></script>
|
||||
<script src="https://unpkg.com/htmx.org@1.9.6"></script>
|
||||
@ -83,6 +83,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{{ message | safe }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% block body %}{% endblock body %}
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user