commit 5854568f28026ac3599c01fdb584db032c8d3e35 Author: bcomsugi Date: Wed Sep 27 15:49:36 2023 +0700 test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..11c466d --- /dev/null +++ b/.gitignore @@ -0,0 +1,171 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +*.pot +*.pyc +__pycache__/ +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ +DN_Excel_files/ +ItemInventory/ +QBbackup/ +.xlsx +.pdf +QBbackup/ +test_folder_source_DeliveryNote/ \ No newline at end of file diff --git a/DASAServer.bat b/DASAServer.bat new file mode 100644 index 0000000..72aa959 --- /dev/null +++ b/DASAServer.bat @@ -0,0 +1,9 @@ +cd "C:\Sources\dasaproject win7\" +echo already cd +cmd /k "cd /d C:\Sources\dasaproject win7\env\Scripts\ & activate & cd /d C:\Sources\dasaproject win7\ & uvicorn main:app --host 0.0.0.0 --port 9999 +echo workon env +echo pause +echo get to env +echo cd "C:\Users\MSi\Documents\Python Project\DBW\Web scrapping" +echo uvicorn main:app --reload +echo start app \ No newline at end of file diff --git a/DASAServer.bat - Shortcut.lnk b/DASAServer.bat - Shortcut.lnk new file mode 100644 index 0000000..fb17bbe Binary files /dev/null and b/DASAServer.bat - Shortcut.lnk differ diff --git a/FASTApiItemReceipt.bat b/FASTApiItemReceipt.bat new file mode 100644 index 0000000..f44b828 --- /dev/null +++ b/FASTApiItemReceipt.bat @@ -0,0 +1,5 @@ +cd "C:\Sources\dasaproject win7\" +echo already cd +cmd /k "cd /d C:\Sources\dasaproject win7\env\Scripts\ & activate & cd /d C:\Sources\dasaproject win7\ & uvicorn main:app --host 0.0.0.0 --port 8888 +echo uvicorn main:app --reload +echo start app \ No newline at end of file diff --git a/GeneralSummaryReport.xml b/GeneralSummaryReport.xml new file mode 100644 index 0000000..e1cf457 --- /dev/null +++ b/GeneralSummaryReport.xml @@ -0,0 +1,146 @@ + + + + + + + ENUMTYPE + BOOLTYPE + + + DATETYPE + DATETYPE + + + + ENUMTYPE + + + + + ENUMTYPE + + IDTYPE + + STRTYPE + + IDTYPE + + STRTYPE + + + + + + ENUMTYPE + + IDTYPE + + STRTYPE + + IDTYPE + + STRTYPE + + + + + + ENUMTYPE + + IDTYPE + + STRTYPE + + IDTYPE + + STRTYPE + + + + + IDTYPE + + STRTYPE + + IDTYPE + + STRTYPE + + + + + ENUMTYPE + + + + DATETYPE + DATETYPE + + + + ENUMTYPE + + + ENUMTYPE + + ENUMTYPE + + ENUMTYPE + BOOLTYPE + + ENUMTYPE + + ENUMTYPE + + ENUMTYPE + + ENUMTYPE + + + + + STRTYPE + STRTYPE + + ENUMTYPE + INTTYPE + INTTYPE + INTTYPE + + + + + ENUMTYPE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ItemInventory140723.xlsx b/ItemInventory140723.xlsx new file mode 100644 index 0000000..fc7abff Binary files /dev/null and b/ItemInventory140723.xlsx differ diff --git a/ItemInventoryQuery.py b/ItemInventoryQuery.py new file mode 100644 index 0000000..ad1785e --- /dev/null +++ b/ItemInventoryQuery.py @@ -0,0 +1,199 @@ +import xml.etree.ElementTree as ET +import win32com.client +import pandas as pd +from datetime import date, datetime +import timeit +import os + +class ItemInventoryQuery: + def __init__(self, *args, **kwargs) -> None: + # print(f'kwargs:{kwargs}') + # print(args) + self.filename=None + if len(args)>0: + self.filename = args[0] + # print(f'args:{args}') + # print(self.filename) + self.IncludeRetElement = kwargs['IncludeRetElement'] if 'IncludeRetElement' in kwargs else None + if not isinstance(self.IncludeRetElement, list): + self.IncludeRetElement = [self.IncludeRetElement] + self.OwnerID = kwargs['OwnerID'] if 'OwnerID' in kwargs else "0" + self.MaxReturned = kwargs['MaxReturned'] if 'MaxReturned' in kwargs else None + if isinstance(self.MaxReturned, int): + self.MaxReturned = str(self.MaxReturned) + self.NameRangeFilter = kwargs['NameRangeFilter'] if 'NameRangeFilter' in kwargs else [] + self.DN = kwargs['DN'] if 'DN' in kwargs else {} + self.TxnDateRangeFilter = kwargs['TxnDateRangeFilter'] if 'TxnDateRangeFilter' in kwargs else None + self.DateMacro = None + if 'DateMacro' in kwargs: + if kwargs['DateMacro'] in ['All', 'Today', 'ThisWeek', 'ThisWeekToDate', 'ThisMonth', 'ThisMonthToDate', 'ThisQuarter', 'ThisQuarterToDate', 'ThisYear', 'ThisYearToDate', 'Yesterday', 'LastWeek', 'LastWeekToDate', 'LastMonth', 'LastMonthToDate', 'LastQuarter', 'LastQuarterToDate', 'LastYear', 'LastYearToDate', 'NextWeek', 'NextFourWeeks', 'NextMonth', 'NextQuarter', 'NextYear']: + self.DateMacro = kwargs['DateMacro'] + self.FromTxnDate = self.validate_date(kwargs['FromTxnDate']) if 'FromTxnDate' in kwargs else None + self.ToTxnDate = self.validate_date(kwargs['ToTxnDate']) if 'ToTxnDate' in kwargs else None + self.ReportEntityFilter = kwargs['ReportEntityFilter'] if 'ReportEntityFilter' in kwargs else None + self.FullName = kwargs['FullName'] if 'FullName' in kwargs else None + # print(self.DateMacro, self.TxnDateRangeFilter, self.FromTxnDate, self.ToTxnDate) + + def create_sub_element(self, ET, parentNode, thisNode, text="\n", whiteSpace = 0, attrib =None): + if type(attrib) is not dict: + attrib = {} + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + def create_QBXML(self): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + ItemInventoryQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "ItemInventoryQueryRq","\n " ) + + if self.MaxReturned is not None: + MaxReturned = self.create_sub_element(ET, ItemInventoryQueryRq, "MaxReturned", self.MaxReturned, 4) + + if len(self.NameRangeFilter)==2: + print(self.NameRangeFilter) + NameRangeFilter = self.create_sub_element(ET, ItemInventoryQueryRq, "NameRangeFilter", "\n ") + FromName = self.create_sub_element(ET, NameRangeFilter, "FromName", self.NameRangeFilter[0]) + ToName = self.create_sub_element(ET, NameRangeFilter, "ToName", self.NameRangeFilter[1]) + + if self.IncludeRetElement: + for x in self.IncludeRetElement: + IncludeRetElement = self.create_sub_element(ET, ItemInventoryQueryRq, "IncludeRetElement", x, 4) + # print(self.OwnerID) + if self.OwnerID is not None: + OwnerID = self.create_sub_element(ET, ItemInventoryQueryRq, "OwnerID", self.OwnerID, 4) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + print(f'create_QBXML->qbxml_query: {qbxml_query}') + return qbxml_query + + def connect_to_quickbooks(self, qbxml_query): + # Connect to Quickbooks + # sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + # sessionManager.OpenConnection('', 'DASA') + # enumfodnc= win32com.client.Dispatch('QBXMLRP2.RequestProcessor') + # print(enumfodnc) + # print(enumfodnc.qbFileOpenDoNotCare) + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA2') + # ticket = sessionManager.BeginSession("z:\\DBW Bogor.qbw", 2) + + ticket = sessionManager.BeginSession("", 2) + + # Send query and receive response + response_string = sessionManager.ProcessRequest(ticket, qbxml_query) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + # print (f'response_string: {response_string}') + return response_string + + def status_ok(self, QBXML): #for ItemInventoryQueryRs + tree = ET.fromstring(QBXML) + GSRQRs = tree.find(".//ItemInventoryQueryRs") + # print(f"GSRQRs:{GSRQRs}") + status_code = GSRQRs.attrib #.get('statusCode') + # print(GSRQRs.attrib) + # print(GSRQRs.attrib['statusCode']) + status=GSRQRs.attrib.get('statusMessage') + + print(f'ItemInventoryQuery->status={status}') + # print('OK' in status) + if 'OK' in status: + return True, status_code + else: + return False, status_code + + def get_data(self, response_string): + tree = ET.fromstring(response_string) + data = tree.findall(".//ItemInventoryRet") + NameFromTaco = [] + FullName = [] + # print(f'get_data->response_string:{response_string}') + # print(data) + for dt in data: + # print(dt.find('FullName').text, ) + for dtextret in dt.findall('DataExtRet'): + + if dtextret.findtext('DataExtName')=='NameFromTaco': + FullName.append(dt.find('FullName').text.strip()) + NameFromTaco.append(dtextret.findtext('DataExtValue').strip()) + # print(f"{dt.find('FullName').text}->{dtextret.find('DataExtName').text} : {dtextret.findtext('DataExtValue')}") + # print() + if len(FullName)>0 and len(NameFromTaco)>0 and len(FullName) == len(NameFromTaco): + # print(f'ItemInventoryQuery->exact len:{len(FullName)}') + return {'FullName': FullName, 'NameFromTaco': NameFromTaco} + else: + print(f'ItemInventoryQuery->Not Exact Len:Fullname={len(FullName)}; NameFromTaco={len(NameFromTaco)}') + return {} + def to_excel(self, filename:str=''): + start = timeit.default_timer() + # print(f'to_excel filename:{self.filename}') + if filename == '': + print("filename is none") + if self.filename != None: + print("self.filename not none") + filename = self.filename + else: + return False, 'Please fill excel filename.' + # print(filename, type(filename)) + if not filename.endswith('.xlsx'): + return False, 'filename has to be excel file(.xlsx)' + # print(self.create_QBXML()) + response_string = self.connect_to_quickbooks(self.create_QBXML()) + + ret, msg = self.status_ok(response_string) + if ret: + df = pd.DataFrame.from_dict(self.get_data(response_string)) + print(df) + if len(df)>0: + df.to_excel(filename, index=False) + modtime = datetime.fromtimestamp(os.path.getmtime(filename)) + print(f"modified Time:{modtime}") + else: + False, 'There is no data(df==0)' + else: + return False, msg + print("The difference of time is :", timeit.default_timer() - start) + return True, f"It takes {format(timeit.default_timer() - start, '.2f')} seconds to update {filename}" + +start = timeit.default_timer() +if __name__ == "__main__": + # ini= ItemInventoryQuery(IncludeRetElement='FullName', OwnerID = "0") + for x in range(0, 1): + # ini= ItemInventoryQuery(IncludeRetElement=['FullName', 'DataExtRet'] , OwnerID = str(x), MaxReturned=None) + # ini= ItemInventoryQuery( OwnerID = str(x), MaxReturned="10", NameRangeFilter=["TSHT:TS WOODGRAIN:TS-252", "TSHT:TS WOODGRAIN:TS-252"]) + # ini= ItemInventoryQuery( OwnerID = str(x), MaxReturned="10", NameRangeFilter=["TSHT:TS LUXURY:TS-L-252", "TSHT:TS LUXURY:TS-L-252"]) + ini= ItemInventoryQuery( OwnerID = str(x), MaxReturned="10") + # ini= ItemInventoryQuery( OwnerID = str(x)) + # ini.to_excel('ItemInventory\ItemInventory_FromQB.xlsx') + itu = ini.connect_to_quickbooks(ini.create_QBXML()) + # print(itu) + ret, msg = ini.status_ok(itu) + if ret: + print("YEAH") + df = pd.DataFrame.from_dict(ini.get_data(itu)) + print(df) + # df.to_excel('ItemInventory\ItemInventory_FromQB.xlsx', index=False) + modtime = datetime.fromtimestamp(os.path.getmtime('ItemInventory\ItemInventory_FromQB.xlsx')) + print(f"modified Time:{modtime}") + break + # print(ini.status_ok(itu)) + # print(ini.create_QBXML()) + print("The difference of time is :", + timeit.default_timer() - start) \ No newline at end of file diff --git a/ItemIventoryQuery.xml b/ItemIventoryQuery.xml new file mode 100644 index 0000000..f65c983 --- /dev/null +++ b/ItemIventoryQuery.xml @@ -0,0 +1,114 @@ + + + + + + + IDTYPE + + STRTYPE + + INTTYPE + + ENUMTYPE + DATETIMETYPE + DATETIMETYPE + + + + ENUMTYPE + STRTYPE + + + + STRTYPE + STRTYPE + + + + + IDTYPE + + STRTYPE + + IDTYPE + + STRTYPE + + + + STRTYPE + GUIDTYPE + + + + + IDTYPE + DATETIMETYPE + DATETIMETYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + BOOLTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + INTTYPE + STRTYPE + + IDTYPE + STRTYPE + + BOOLTYPE + + IDTYPE + STRTYPE + + STRTYPE + PRICETYPE + + IDTYPE + STRTYPE + + STRTYPE + PRICETYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + QUANTYPE + QUANTYPE + QUANTYPE + PRICETYPE + QUANTYPE + QUANTYPE + GUIDTYPE + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + + \ No newline at end of file diff --git a/ItemReceipt.ini b/ItemReceipt.ini new file mode 100644 index 0000000..9c8bd74 --- /dev/null +++ b/ItemReceipt.ini @@ -0,0 +1,5 @@ +[Section 1] +key1 = myval1 +key2 = value2 +#item_inventory_path = ItemInventory\ItemInventory140723.xlsx + diff --git a/ItemReceiptXml.xml b/ItemReceiptXml.xml new file mode 100644 index 0000000..f369498 --- /dev/null +++ b/ItemReceiptXml.xml @@ -0,0 +1,272 @@ + + + + + + + + IDTYPE + STRTYPE + + DATETYPE + STRTYPE + STRTYPE + GUIDTYPE + IDTYPE + + + IDTYPE + STRTYPE + + STRTYPE + QUANTYPE + STRTYPE + PRICETYPE + AMTTYPE + + IDTYPE + IDTYPE + + + + STRTYPE + + + + + IDTYPE + DATETIMETYPE + DATETIMETYPE + STRTYPE + INTTYPE + + IDTYPE + STRTYPE + + + + IDTYPE + STRTYPE + + + + IDTYPE + STRTYPE + + + DATETYPE + AMTTYPE + + IDTYPE + STRTYPE + + FLOATTYPE + AMTTYPE + STRTYPE + STRTYPE + BOOLTYPE + + IDTYPE + STRTYPE + + GUIDTYPE + + IDTYPE + + ENUMTYPE + DATETYPE + STRTYPE + + ENUMTYPE + AMTTYPE + + + IDTYPE + + IDTYPE + STRTYPE + + AMTTYPE + STRTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + ENUMTYPE + + IDTYPE + STRTYPE + + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + + IDTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + STRTYPE + + STRTYPE + + STRTYPE + STRTYPE + QUANTYPE + STRTYPE + + IDTYPE + STRTYPE + + PRICETYPE + AMTTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + ENUMTYPE + + IDTYPE + STRTYPE + + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + + IDTYPE + + IDTYPE + STRTYPE + + STRTYPE + QUANTYPE + STRTYPE + + IDTYPE + STRTYPE + + AMTTYPE + + IDTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + STRTYPE + + STRTYPE + + STRTYPE + STRTYPE + QUANTYPE + STRTYPE + + IDTYPE + STRTYPE + + PRICETYPE + AMTTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + ENUMTYPE + + IDTYPE + STRTYPE + + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + GUIDTYPE + STRTYPE + STRTYPE + + + + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + + IDTYPE + + GUIDTYPE + + IDTYPE + + INTTYPE + STRTYPE + GUIDTYPE + + + + \ No newline at end of file diff --git a/PriceLevelQuery.py b/PriceLevelQuery.py new file mode 100644 index 0000000..aaec7fd --- /dev/null +++ b/PriceLevelQuery.py @@ -0,0 +1,146 @@ +#!usr/bin/python +import win32com.client +import xml.etree.ElementTree as ET +import json +import xmltodict + +# Connect to Quickbooks +sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") +sessionManager.OpenConnection('', 'Test qbXML Request') +ticket = sessionManager.BeginSession("C:\Quickbooks Bogor\qb test\distrindo bakti wutama.qbw", 0) + +# Send query and receive response +qbxml_query = """ + + + + + + Contains + TS-I502 + + QuantityOnHand + + + +""" +qbxml_query = """ + + + + + A + B + + + + +""" +qbxml_query = """ +AB""" + +qbxml_query1 = """ + + + + + QuantityOnHand + QuantityOnOrder + QuantityOnSalesOrder + FullName + Name + + + +""" + +root = ET.Element("QBXML") +root.tail = "\n " +root.text = "\n " +QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") +QBXMLMsgsRq.set("onError", "stopOnError") +QBXMLMsgsRq.tail = "\n" +QBXMLMsgsRq.text = "\n " +PriceLevelQueryRq = ET.SubElement(QBXMLMsgsRq, "PriceLevelQueryRq") +#PriceLevelQueryRq.set("metaData", "MetaDataAndResponseData") +PriceLevelQueryRq.set("metaData", "NoMetaData") +PriceLevelQueryRq.tail = "\n " +PriceLevelQueryRq.text = "\n " +FullName = ET.SubElement(PriceLevelQueryRq, "FullName") +FullName.text = "A" +FullName.tail = "\n " +FullName = ET.SubElement(PriceLevelQueryRq, "FullName") +FullName.text = "C" +FullName.tail = "\n " + +#mydata = ET.tostring(root, encoding = "unicode", method = "xml") +mydata = ET.tostring(root, encoding = "unicode") +#mydata = ET.tostring(root).decode() +print (mydata,type(mydata)) +qbxml_query1 = """""" +qbxml_query1 = qbxml_query1 + """""" +qbxml_query1 = qbxml_query1 + "\n" + mydata +print("") +print(qbxml_query1, type(qbxml_query1)) +print("") +#print(qbxml_query, type(qbxml_query)) + + + +tree = ET.ElementTree(root) +print("test",tree) + +#response_string = sessionManager.ProcessRequest(ticket, qbxml_query1) + +# Disconnect from Quickbooks +sessionManager.EndSession(ticket) # Close the company file +sessionManager.CloseConnection() # Close the connection +#print (response_string) +# Parse the response into an Element Tree and peel away the layers of response +#QBXML = xml.etree.ElementTree.fromstring(response_string) +QBXML = ET.fromstring(response_string) +print("") +#print(QBXML) +#print(QBXML) +datadict=xmltodict.parse(response_string) +#print(datadict) +jsondata=json.dumps(datadict) +#print(jsondata) +ddict=json.loads(jsondata) +#print(ddict) +QBXMLMsgsRs = QBXML.find('QBXMLMsgsRs') +#InventoryAdjustmentQueryRs = QBXMLMsgsRs.getiterator("InventoryAdjustmentRet") +#InventoryAdjustmentQueryRs = QBXMLMsgsRs.iter("ItemInventoryRet") +PriceLevelQueryRs = QBXMLMsgsRs.iter("PriceLevelRet") +#print (PriceLevelQueryRs) +PriceLevelRet = ddict["QBXML"]["QBXMLMsgsRs"]["PriceLevelQueryRs"]["PriceLevelRet"] + +#print (priceLevelPerItemRet) + +for priceLevelPerItemRetList in PriceLevelRet: + #print(priceLevelPerItemRetList) +#priceLevelPerItemRet = priceLevelPerItemRet["PriceLevelPerItemRet"] + + for PriceLevelPerItemRet in priceLevelPerItemRetList["PriceLevelPerItemRet"]: + pass + print(priceLevelPerItemRetList["Name"],PriceLevelPerItemRet["ItemRef"]["FullName"], PriceLevelPerItemRet["CustomPrice"]) + + + +# for PriceLevelRet in PriceLevelQueryRs: + # print(PriceLevelRet) +# # try: + # PLT = PriceLevelRet.find('PriceLevelType').text + # IsActive = PriceLevelRet.find('IsActive').text + # #txnid = PriceLevelRet.find('ListID').text + # name = PriceLevelRet.find('Name').text + # PriceLevelPerItemRet = PriceLevelRet.iter("PriceLevelPerItemRet") + # for ItemRef in PriceLevelPerItemRet: + # print(ItemRef) + # FullName = ItemRef.find('FullName').text + # CustomPrice = PriceLevelRet.find('CustomPrice').text + # print(FullName, name, PLT, CustomPrice) +# # except AttributeError: + # # print("attrib err") + # # except: + # # print("err") diff --git a/PriceLevelQueryv2.py b/PriceLevelQueryv2.py new file mode 100644 index 0000000..0f9fcdd --- /dev/null +++ b/PriceLevelQueryv2.py @@ -0,0 +1,147 @@ +#!usr/bin/python +import win32com.client +import xml.etree.ElementTree as ET +import json +import xmltodict + +# Connect to Quickbooks +sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") +sessionManager.OpenConnection('', 'Test qbXML Request') +#ticket = sessionManager.BeginSession("C:\Quickbooks Bogor\qb test\distrindo bakti wutama.qbw", 0) +ticket = sessionManager.BeginSession("", 0) + +# Send query and receive response +qbxml_query = """ + + + + + + Contains + TS-I502 + + QuantityOnHand + + + +""" +qbxml_query = """ + + + + + A + B + + + + +""" +qbxml_query = """ +AB""" + +qbxml_query1 = """ + + + + + QuantityOnHand + QuantityOnOrder + QuantityOnSalesOrder + FullName + Name + + + +""" + +root = ET.Element("QBXML") +root.tail = "\n " +root.text = "\n " +QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") +QBXMLMsgsRq.set("onError", "stopOnError") +QBXMLMsgsRq.tail = "\n" +QBXMLMsgsRq.text = "\n " +PriceLevelQueryRq = ET.SubElement(QBXMLMsgsRq, "PriceLevelQueryRq") +#PriceLevelQueryRq.set("metaData", "MetaDataAndResponseData") +PriceLevelQueryRq.set("metaData", "NoMetaData") +PriceLevelQueryRq.tail = "\n " +PriceLevelQueryRq.text = "\n " +FullName = ET.SubElement(PriceLevelQueryRq, "FullName") +FullName.text = "A" +FullName.tail = "\n " +FullName = ET.SubElement(PriceLevelQueryRq, "FullName") +FullName.text = "C" +FullName.tail = "\n " + +#mydata = ET.tostring(root, encoding = "unicode", method = "xml") +mydata = ET.tostring(root, encoding = "unicode") +#mydata = ET.tostring(root).decode() +print (mydata,type(mydata)) +qbxml_query1 = """""" +qbxml_query1 = qbxml_query1 + """""" +qbxml_query1 = qbxml_query1 + "\n" + mydata +print("") +print(qbxml_query1, type(qbxml_query1)) +print("") +#print(qbxml_query, type(qbxml_query)) + + + +tree = ET.ElementTree(root) +print("test",tree) + +response_string = sessionManager.ProcessRequest(ticket, qbxml_query1) + +# Disconnect from Quickbooks +sessionManager.EndSession(ticket) # Close the company file +sessionManager.CloseConnection() # Close the connection +print (response_string) +# Parse the response into an Element Tree and peel away the layers of response +#QBXML = xml.etree.ElementTree.fromstring(response_string) +QBXML = ET.fromstring(response_string) +print("") +#print(QBXML) +#print(QBXML) +datadict=xmltodict.parse(response_string) +#print(datadict) +jsondata=json.dumps(datadict) +#print(jsondata) +ddict=json.loads(jsondata) +#print(ddict) +QBXMLMsgsRs = QBXML.find('QBXMLMsgsRs') +#InventoryAdjustmentQueryRs = QBXMLMsgsRs.getiterator("InventoryAdjustmentRet") +#InventoryAdjustmentQueryRs = QBXMLMsgsRs.iter("ItemInventoryRet") +PriceLevelQueryRs = QBXMLMsgsRs.iter("PriceLevelRet") +#print (PriceLevelQueryRs) +PriceLevelRet = ddict["QBXML"]["QBXMLMsgsRs"]["PriceLevelQueryRs"]["PriceLevelRet"] + +#print (priceLevelPerItemRet) + +for priceLevelPerItemRetList in PriceLevelRet: + #print(priceLevelPerItemRetList) +#priceLevelPerItemRet = priceLevelPerItemRet["PriceLevelPerItemRet"] + + for PriceLevelPerItemRet in priceLevelPerItemRetList["PriceLevelPerItemRet"]: + pass + print(priceLevelPerItemRetList["Name"],PriceLevelPerItemRet["ItemRef"]["FullName"], PriceLevelPerItemRet["CustomPrice"]) + + + +# for PriceLevelRet in PriceLevelQueryRs: + # print(PriceLevelRet) +# # try: + # PLT = PriceLevelRet.find('PriceLevelType').text + # IsActive = PriceLevelRet.find('IsActive').text + # #txnid = PriceLevelRet.find('ListID').text + # name = PriceLevelRet.find('Name').text + # PriceLevelPerItemRet = PriceLevelRet.iter("PriceLevelPerItemRet") + # for ItemRef in PriceLevelPerItemRet: + # print(ItemRef) + # FullName = ItemRef.find('FullName').text + # CustomPrice = PriceLevelRet.find('CustomPrice').text + # print(FullName, name, PLT, CustomPrice) +# # except AttributeError: + # # print("attrib err") + # # except: + # # print("err") diff --git a/SO_to_Inv/CustomerQuery.py b/SO_to_Inv/CustomerQuery.py new file mode 100644 index 0000000..d013d45 --- /dev/null +++ b/SO_to_Inv/CustomerQuery.py @@ -0,0 +1,144 @@ +import xml.etree.ElementTree as ET +import win32com.client +import xmltodict +import pprint +import datetime +import pandas as pd +from datetime import date +import timeit +import os + +class CustomerQuery: + def __init__(self, **kwargs) -> None: + # print(f'kwargs:{kwargs}') + # print(args) + self.CustomerPriceLevelNames = [] + self.SPPriceLevelNames = [] + self.CustomerFullNames = [] + self.item_inventory_path = "ItemInventory" + self._filename = "CustomerList.xlsx" + # self._df_customer = pd.read_excel(os.path.join(os.getcwd(), self.item_inventory_path, self._filename), usecols=['FullName', 'PriceLevelName', 'Special Cust'],) + # print(self._df_customer) + # print(type(self._df_customer.loc[(self._df_customer['FullName']=="ECO:0:ECO-002") & (self._df_customer['PriceLevelName']=="T 202202")].values.tolist()[0][2])) + self.IncludeRetElement = kwargs['IncludeRetElement'] if 'IncludeRetElement' in kwargs else [] + self.TxnDateRangeFilter = kwargs['TxnDateRangeFilter'] if 'TxnDateRangeFilter' in kwargs else None + self.FullName = kwargs['FullName'] if 'FullName' in kwargs else None + + def get_customer_pricelevel_list(self, response_string): + QBXML = ET.fromstring(response_string) + CustomerRets = QBXML.findall('.//CustomerRet') + # print(f'CustomerRets:{CustomerRets}') + + for CustomerRet in CustomerRets: + CustomerFullName = None + PriceLevelName = None + SP_PriceLevelName = None + CustomerFullName = CustomerRet.find('FullName').text + PriceLevelName = CustomerRet.find('.//PriceLevelRef') + if PriceLevelName: + PriceLevelName = PriceLevelName.find("FullName").text + # print(f'PriceLevelName:{PriceLevelName}') + DataExtRets = CustomerRet.findall('.//DataExtRet') + SP_PriceLevelName = None + if len(DataExtRets)>0: + for DataExtRet in DataExtRets: + DataExtName = DataExtRet.find('DataExtName').text + DataExtValue = DataExtRet.find('DataExtValue').text + if DataExtName.lower() == 'special cust'.lower(): + SP_PriceLevelName = DataExtValue.upper() + break + self.CustomerPriceLevelNames.append(PriceLevelName) + self.SPPriceLevelNames.append(SP_PriceLevelName) + self.CustomerFullNames.append(CustomerFullName) + # print(self.CustomerFullNames, self.CustomerPriceLevelNames, self.SPPriceLevelNames) + Customer = {} + Customer['FullName']=self.CustomerFullNames + Customer['PriceLevelName']=self.CustomerPriceLevelNames + Customer['SPName']= self.SPPriceLevelNames + # print(Customer) + _df = pd.DataFrame.from_dict(Customer) + print(_df) + _df.to_excel(os.path.join(os.getcwd(), self.item_inventory_path, self._filename), index=False) + return PriceLevelName, SP_PriceLevelName + + def create_customerquery_QBXML(self ): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + CustomerQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "CustomerQueryRq","\n " ) + # FullName = self.create_sub_element(ET, CustomerQueryRq, "FullName", self.FullName, 6) + IncludeRetElement = ['FullName', 'PriceLevelRef', 'DataExtRet'] + for x in IncludeRetElement: + IncludeRetElement = self.create_sub_element(ET, CustomerQueryRq, "IncludeRetElement", x, 4) + OwnerID = self.create_sub_element(ET, CustomerQueryRq, "OwnerID", "0", 6) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + print(f'create_customer_QBXML->qbxml_query: {qbxml_query}') + response_string=self.connect_to_quickbooks(qbxml_query) + + return response_string + + def create_sub_element(self, ET, parentNode, thisNode, text="\n", whiteSpace = 0, attrib =None): + if type(attrib) is not dict: + attrib = {} + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + def connect_to_quickbooks(self, qbxml_query): + # Connect to Quickbooks + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA2') + # ticket = sessionManager.BeginSession("z:\\DBW Bogor.qbw", 2) + ticket = sessionManager.BeginSession("", 2) + + # Send query and receive response + response_string = sessionManager.ProcessRequest(ticket, qbxml_query) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + # print (f'response_string:{response_string}') + return response_string + + def status_ok(self, QBXML): #for CustomerRs + + tree = ET.fromstring(QBXML) + + GSRQRs = tree.find(".//CustomerRs") + # print(f"GSRQRs:{GSRQRs}") + status_code = GSRQRs.attrib #.get('statusCode') + # print(GSRQRs.attrib) + # print(GSRQRs.attrib['statusCode']) + status=GSRQRs.attrib.get('statusMessage') + + print(f'status={status}') + if 'OK' in status: + return True, status_code + else: + return False, status_code + +if __name__ == '__main__': + starttime = timeit.default_timer() + # ini=SalesOrderQuery(FullName= '999 HPL', IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'IsManuallyClosed', 'IsFullyInvoiced']) + + ini=CustomerQuery() + iya = ini.create_customerquery_QBXML() + # print(iya) + ini.get_customer_pricelevel_list(iya) + + print("The time difference is :", timeit.default_timer() - starttime) \ No newline at end of file diff --git a/SO_to_Inv/InvoiceAdd.xml b/SO_to_Inv/InvoiceAdd.xml new file mode 100644 index 0000000..5259754 --- /dev/null +++ b/SO_to_Inv/InvoiceAdd.xml @@ -0,0 +1,454 @@ + + + + + + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + DATETYPE + STRTYPE + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + BOOLTYPE + BOOLTYPE + STRTYPE + + IDTYPE + STRTYPE + + DATETYPE + + IDTYPE + STRTYPE + + STRTYPE + DATETYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + STRTYPE + + IDTYPE + STRTYPE + + BOOLTYPE + BOOLTYPE + BOOLTYPE + + IDTYPE + STRTYPE + + STRTYPE + FLOATTYPE + GUIDTYPE + IDTYPE + + IDTYPE + AMTTYPE + BOOLTYPE + + + + + IDTYPE + STRTYPE + + STRTYPE + QUANTYPE + STRTYPE + + PRICETYPE + + PERCENTTYPE + + + IDTYPE + STRTYPE + + + + IDTYPE + STRTYPE + + AMTTYPE + + ENUMTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + STRTYPE + + STRTYPE + + DATETYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + STRTYPE + STRTYPE + + IDTYPE + IDTYPE + + + GUIDTYPE + STRTYPE + STRTYPE + + + + + + IDTYPE + STRTYPE + + QUANTYPE + STRTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + GUIDTYPE + STRTYPE + STRTYPE + + + + + STRTYPE + + + + + IDTYPE + DATETIMETYPE + DATETIMETYPE + STRTYPE + INTTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + DATETYPE + STRTYPE + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + BOOLTYPE + BOOLTYPE + STRTYPE + + IDTYPE + STRTYPE + + DATETYPE + + IDTYPE + STRTYPE + + STRTYPE + DATETYPE + + IDTYPE + STRTYPE + + AMTTYPE + + IDTYPE + STRTYPE + + PERCENTTYPE + AMTTYPE + AMTTYPE + AMTTYPE + + IDTYPE + STRTYPE + + FLOATTYPE + AMTTYPE + STRTYPE + BOOLTYPE + + IDTYPE + STRTYPE + + BOOLTYPE + BOOLTYPE + BOOLTYPE + + IDTYPE + STRTYPE + + AMTTYPE + DATETYPE + STRTYPE + GUIDTYPE + + IDTYPE + + ENUMTYPE + DATETYPE + STRTYPE + + ENUMTYPE + AMTTYPE + + + + IDTYPE + + IDTYPE + STRTYPE + + STRTYPE + QUANTYPE + STRTYPE + + IDTYPE + STRTYPE + + + PRICETYPE + + PERCENTTYPE + + + IDTYPE + STRTYPE + + AMTTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + STRTYPE + + STRTYPE + + STRTYPE + DATETYPE + + IDTYPE + STRTYPE + + STRTYPE + STRTYPE + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + + IDTYPE + + IDTYPE + STRTYPE + + STRTYPE + QUANTYPE + STRTYPE + + IDTYPE + STRTYPE + + BOOLTYPE + AMTTYPE + + IDTYPE + + IDTYPE + STRTYPE + + STRTYPE + QUANTYPE + STRTYPE + + IDTYPE + STRTYPE + + + PRICETYPE + + PERCENTTYPE + + + IDTYPE + STRTYPE + + AMTTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + STRTYPE + + STRTYPE + + STRTYPE + DATETYPE + + IDTYPE + STRTYPE + + STRTYPE + STRTYPE + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + + IDTYPE + + GUIDTYPE + + IDTYPE + + INTTYPE + STRTYPE + GUIDTYPE + + + + diff --git a/SO_to_Inv/InvoiceQuery.py b/SO_to_Inv/InvoiceQuery.py new file mode 100644 index 0000000..39aa589 --- /dev/null +++ b/SO_to_Inv/InvoiceQuery.py @@ -0,0 +1,587 @@ +import xml.etree.ElementTree as ET +import win32com.client +import xmltodict +import pprint +import datetime +import pandas as pd +from datetime import date +import timeit +import os + +class InvoiceQuery: + def __init__(self, **kwargs) -> None: + # print(f'kwargs:{kwargs}') + # print(args) + # self.InvoiceList=[] + self.PriceLevelName = None + self.SPPriceLevelName = None + self.item_inventory_path = "ItemInventory" + self.price_level_filename = "PriceLevel.xlsx" + self._df_price_level = pd.read_excel(os.path.join(os.getcwd(), 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])) + self.FullName = kwargs['FullName'] if 'FullName' in kwargs else None + + self.CustomerPriceLevelName_filename = "CustomerList.xlsx" + self._df_customer = pd.read_excel(os.path.join(os.getcwd(), 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.DN = kwargs['DN'] if 'DN' in kwargs else {} + self.Reuse = kwargs['Reuse'] if 'Reuse' in kwargs else None + + self.InvoiceList= kwargs['InvoiceList'] if 'InvoiceList' in kwargs else [] + self.InvoiceList = None + self.InvoiceType = kwargs['InvoiceType'] if 'InvoiceType' in kwargs else 'SalesByCustomerSummary' + self.IncludeLineItems = kwargs['IncludeLineItems'] if 'IncludeLineItems' in kwargs else 'true' + self.IncludeRetElement = kwargs['IncludeRetElement'] if 'IncludeRetElement' in kwargs else [] + self.TxnDateRangeFilter = kwargs['TxnDateRangeFilter'] if 'TxnDateRangeFilter' in kwargs else None + self.DateMacro = None + self.MaxReturned = kwargs['MaxReturned'] if 'MaxReturned' in kwargs else '1' + + if 'DateMacro' in kwargs: + if kwargs['DateMacro'] in ['All', 'Today', 'ThisWeek', 'ThisWeekToDate', 'ThisMonth', 'ThisMonthToDate', 'ThisQuarter', 'ThisQuarterToDate', 'ThisYear', 'ThisYearToDate', 'Yesterday', 'LastWeek', 'LastWeekToDate', 'LastMonth', 'LastMonthToDate', 'LastQuarter', 'LastQuarterToDate', 'LastYear', 'LastYearToDate', 'NextWeek', 'NextFourWeeks', 'NextMonth', 'NextQuarter', 'NextYear']: + self.DateMacro = kwargs['DateMacro'] + today = datetime.date.today() + deltatoday = today - datetime.timedelta(days = 74) + print(today, deltatoday) + self.FromTxnDate = self.validate_date(kwargs['FromTxnDate']) if 'FromTxnDate' in kwargs else deltatoday + self.ToTxnDate = self.validate_date(kwargs['ToTxnDate']) if 'ToTxnDate' in kwargs else today + self.ReportEntityFilter = kwargs['ReportEntityFilter'] if 'ReportEntityFilter' in kwargs else None + + # print(self.DateMacro, self.TxnDateRangeFilter, self.FromTxnDate, self.ToTxnDate) + # 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.get_sales_order_header() + + def create_sub_element(self, ET, parentNode, thisNode, text="\n", whiteSpace = 0, attrib =None): + if type(attrib) is not dict: + attrib = {} + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + def create_QBXML(self): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + InvoiceQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "InvoiceQueryRq","\n " ) + # InvoiceType = self.create_sub_element(ET, InvoiceQueryRq, 'InvoiceType', self.InvoiceType) + # if self.FullName: + # EntityFilter = self.create_sub_element(ET, InvoiceQueryRq, 'EntityFilter', "\n ") + # FullName = self.create_sub_element(ET, EntityFilter, "FullName", self.FullName, 6) + # if self.MaxReturned: + # MaxReturned = self.create_sub_element(ET, InvoiceQueryRq, 'MaxReturned', self.MaxReturned, 6) + if self.DateMacro: + TxnDateRangeFilter = self.create_sub_element(ET, InvoiceQueryRq, "TxnDateRangeFilter", "\n ",) + InvoiceType = self.create_sub_element(ET, TxnDateRangeFilter, "DateMacro", self.DateMacro) + # InvoiceType = self.create_sub_element(ET, InvoiceQueryRq, "DateMacro", self.DateMacro) + + elif type(self.FromTxnDate) is datetime.date or type(self.ToTxnDate) is datetime.date: + TxnDateRangeFilter = self.create_sub_element(ET, InvoiceQueryRq, "TxnDateRangeFilter", "\n ",) + if type(self.FromTxnDate) is datetime.date: + FromTxnDate = self.create_sub_element(ET, TxnDateRangeFilter, "FromTxnDate", self.FromTxnDate.strftime('%Y-%m-%d'),4) + if type(self.ToTxnDate) is datetime.date: + ToTxnDate = self.create_sub_element(ET, TxnDateRangeFilter, "ToTxnDate", self.ToTxnDate.strftime('%Y-%m-%d')) + if self.IncludeLineItems: + IncludeLineItems = self.create_sub_element(ET, InvoiceQueryRq, "IncludeLineItems", self.IncludeLineItems, 4) + if len(self.IncludeRetElement)>0: + for x in self.IncludeRetElement: + IncludeRetElement = self.create_sub_element(ET, InvoiceQueryRq, "IncludeRetElement", x, 4) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + # print(f'create_QBXML->qbxml_query: {qbxml_query}') + return qbxml_query + + def get_customer_pricelevel(self, response_string): + QBXML = ET.fromstring(response_string) + PriceLevelName = QBXML.find('.//PriceLevelRef') + if PriceLevelName: + + PriceLevelName = PriceLevelName.find("FullName").text + print(f'PriceLevelName:{PriceLevelName}') + DataExtRets = QBXML.findall('.//DataExtRet') + SP_PriceLevelName = None + if len(DataExtRets)>0: + for DataExtRet in DataExtRets: + DataExtName = DataExtRet.find('DataExtName').text + DataExtValue = DataExtRet.find('DataExtValue').text + if DataExtName.lower() == 'special cust'.lower(): + SP_PriceLevelName = DataExtValue.upper() + break + self.PriceLevelName = PriceLevelName + self.SPPriceLevelName = SP_PriceLevelName + return PriceLevelName, SP_PriceLevelName + + def create_customerquery_QBXML(self ): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + CustomerQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "CustomerQueryRq","\n " ) + # InvoiceType = self.create_sub_element(ET, CustomerQueryRq, 'InvoiceType', self.InvoiceType) + FullName = self.create_sub_element(ET, CustomerQueryRq, "FullName", self.FullName, 6) + IncludeRetElement = ['FullName', 'PriceLevelRef', 'DataExtRet'] + for x in IncludeRetElement: + IncludeRetElement = self.create_sub_element(ET, CustomerQueryRq, "IncludeRetElement", x, 4) + OwnerID = self.create_sub_element(ET, CustomerQueryRq, "OwnerID", "0", 6) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + print(f'create_customer_QBXML->qbxml_query: {qbxml_query}') + response_string=self.connect_to_quickbooks(qbxml_query) + + return self.get_customer_pricelevel(response_string) + return response_string + + def create_invoiceadd_QBXML(self): + print('create_ionvoiceadd_QBXML') + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + InvoiceAddRq = self.create_sub_element(ET, QBXMLMsgsRq, "InvoiceAddRq", "\n ",2 ) + InvoiceAdd = self.create_sub_element(ET, InvoiceAddRq, "InvoiceAdd", "\n ",4 ) + CustomerRef = self.create_sub_element(ET, InvoiceAdd, "CustomerRef", "\n ",8 ) + FullName = self.create_sub_element(ET, CustomerRef, "FullName", self.InvoiceList[0]['CustomerFullName'], 8 ) + TemplateRef = self.create_sub_element(ET, InvoiceAdd, "TemplateRef", "\n ", 8 ) + TemplateFullName = self.create_sub_element(ET, TemplateRef, "FullName", "DBW Invoice (11%)", 8 ) + today = str(date.today()) + TxnDate = self.create_sub_element(ET, InvoiceAdd, "TxnDate", today,8) # self.DN['TxnDate'], 8 ) + + RefNumber = self.create_sub_element(ET, InvoiceAdd, "RefNumber", today,8 ) # self.DN['DNRefNum'], 8 ) + ShipDate = self.create_sub_element(ET, InvoiceAdd, "ShipDate", today,8) # self.DN['TxnDate'], 8 ) + # Memo = self.create_sub_element(ET, InvoiceAdd, "Memo", self.DN['Memo'], 10 ) + disc_amount = 0 + for soidx, salesorder in enumerate(self.InvoiceList): + SOTxnId = salesorder['TxnID'] + disc_amount+=int(salesorder['Disc_Amount']) + print(f'create_invoiceadd_QBXML->SOTxnId: {SOTxnId}') + for itemline in salesorder['InvoiceLineRet']: + # 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.InvoiceList)-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) + + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + 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)}") + + return qbxml_query + + + def connect_to_quickbooks(self, qbxml_query): + # Connect to Quickbooks + # sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + # sessionManager.OpenConnection('', 'DASA') + # enumfodnc= win32com.client.Dispatch('QBXMLRP2.RequestProcessor') + # print(enumfodnc) + # print(enumfodnc.qbFileOpenDoNotCare) + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA2') + # ticket = sessionManager.BeginSession("z:\\DBW Bogor.qbw", 2) + + ticket = sessionManager.BeginSession("", 2) + + # Send query and receive response + response_string = sessionManager.ProcessRequest(ticket, qbxml_query) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + # print (f'response_string:{response_string}') + return response_string + + def __str__(self, *args) -> str: + # return str(self._get_datarow(self.connect_to_quickbooks(self.create_QBXML()))) + # print("__str__") + return str(self.get_sales_order_header()) + # return "hello" + + def get_sales_order_header(self, *args): + return self._get_sales_order_header(self.connect_to_quickbooks(self.create_QBXML())) + + def status_ok(self, QBXML): #for InvoiceAddRS + + tree = ET.fromstring(QBXML) + + GSRQRs = tree.find(".//InvoiceQueryRs") + # print(f"GSRQRs:{GSRQRs}") + status_code = GSRQRs.attrib #.get('statusCode') + # print(GSRQRs.attrib) + # print(GSRQRs.attrib['statusCode']) + status=GSRQRs.attrib.get('statusMessage') + + print(f'status={status}') + if 'OK' in status: + return True, status_code + else: + return False, status_code + + + def _get_sales_order_header(self, response_string): + print('_get_sales_order_header') + # print(f'responsestring:{response_string}') + QBXML = ET.fromstring(response_string) + datadict = {} + Invoicedict = {} + _Invoicelist = [] + InvoiceRets = QBXML.findall('.//InvoiceRet') + # print(InvoiceRets) + for InvoiceRet in InvoiceRets: + RefNumber = InvoiceRet.find('RefNumber').text + # Memo = InvoiceRet.find('Memo').text + CustomerFullName = InvoiceRet.find('CustomerRef/FullName').text + TxnID = InvoiceRet.find('TxnID').text + TotalAmount = InvoiceRet.find('TotalAmount').text + IsFullyInvoiced = InvoiceRet.find('IsFullyInvoiced').text + IsManuallyClosed = InvoiceRet.find('IsManuallyClosed').text + # print(CustomerFullName, TxnID, TotalAmount) + Invoicedict = {'RefNumber':RefNumber, 'CustomerFullName':CustomerFullName, 'TxnID':TxnID, + 'TotalAmount':TotalAmount, 'IsFullyInvoiced':IsFullyInvoiced, 'IsManuallyClosed':IsManuallyClosed, 'InvoiceLineRet':[]} + InvoiceLineRet = InvoiceRet.findall('InvoiceLineRet') + # print(len(InvoiceLineRet)) + if len(InvoiceLineRet) > 0: + disc_amount=0 + for InvoiceLineRet in InvoiceLineRet: + TxnLineID = InvoiceLineRet.find('TxnLineID').text + ItemFullName = InvoiceLineRet.find('ItemRef/FullName').text + Quantity = InvoiceLineRet.find('Quantity').text + UnitOfMeasure = InvoiceLineRet.find('UnitOfMeasure').text + Rate = float(InvoiceLineRet.find('Rate').text) + + Amount = float(InvoiceLineRet.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])) + 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])) + 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 = InvoiceLineRet.find('Invoiced').text + LineIsManuallyClosed = InvoiceLineRet.find('IsManuallyClosed').text + # print(TxnLineID, ItemFullName) + BackOrdered = float(Quantity) - float(Invoiced) + if BackOrdered: + InvoiceLinedict = {'TxnLineID':TxnLineID, + 'ItemFullName':ItemFullName, + 'Quantity':Quantity, + 'UOM':UnitOfMeasure, + 'Rate':Rate, + 'Amount':Amount, + 'BackOrdered':BackOrdered, + 'Invoiced':Invoiced, + 'LineIsManuallyClosed':LineIsManuallyClosed, + } + Invoicedict['InvoiceLineRet'].append(InvoiceLinedict) + Invoicedict['Disc_Amount']=disc_amount + _Invoicelist.append(Invoicedict) + # print(_Invoicelist) + self.InvoiceList=_Invoicelist + # print(f'_get_sales_order_header->Salesorderlist: {self.InvoiceList}') + return self.InvoiceList + + def addDiscountToInvoiceList(self, _dict:dict): + print("addDiscountToInvoiceList") + + + def addDNQtyToInvoiceList(self, _dict:dict): + _bolfoundrefnum=False + _bol_dictisadded=False + Error_msg = None + for poidx, _po in enumerate(self.InvoiceList): + if _po['RefNumber']==_dict['RefNum']: + _bolfoundrefnum=True + if len(_po['InvoiceLineRet'])>0: + for polineidx, _poline in enumerate(_po['InvoiceLineRet']): + pass + if _poline['ItemFullName']==_dict['FullName']: + if _poline['UOM'].upper()==_dict['UOM'].upper(): + # first do UOM in _dict convert treatment + QuantityIn_dict = _dict['Quantity'] + if _dict['UOM'].upper().startswith('ROLL_'): + print(f"addDNQtyToInvoiceList->DNqty:{_dict['Quantity']}, Roll_:{_dict['UOM'].split('_')[1]}") + QuantityIn_dict = _dict['Quantity'] * int(_dict['UOM'].split("_")[1]) + pass + elif _dict['UOM'].upper() == 'BOX' and _dict['Item No'].upper() == "CUTTER": + print("addDNQtyToInvoiceList->cutter") + elif _dict['UOM'].upper() == 'BOX' and (_dict['Item No'].upper().startswith("EB-") or _dict['Item No'].upper().startswith("TA-")): + print("addDNQtyToInvoiceList->LEM") + if _dict['Item No'].split("-")[1].endswith("1006"): + QuantityIn_dict = QuantityIn_dict * 12 + elif _dict['Item No'].split("-")[1].endswith("1025"): + QuantityIn_dict = QuantityIn_dict * 6 + elif _dict['Item No'].split("-")[1].endswith("1100"): + pass + print("1100 lem") + elif _dict['UOM'].upper() == 'BOX' and (_dict['Item No'].upper().startswith("TL-") or _dict['Item No'].upper().startswith("TFL-")): + print("addDNQtyToInvoiceList->Lock") + QuantityIn_dict = QuantityIn_dict * 20 + elif _dict['UOM'].upper() == 'BOX' and _dict['Item No'].upper() == "EDG-TRIMMER": + QuantityIn_dict = QuantityIn_dict * 12 #coz box of 12 + + + if _poline['BackOrdered']>=QuantityIn_dict: + self.InvoiceList[poidx]['InvoiceLineRet'][polineidx]['DNQuantity']=float(QuantityIn_dict) + _bol_dictisadded = True + else: + print(f"{_poline['ItemFullName']} BackOrdered < Qty in DN {_poline['BackOrdered']}<{QuantityIn_dict}") + Error_msg = f"BackOrdered < Qty in DN {_poline['BackOrdered']}<{QuantityIn_dict}" + else: + # print(f"UOM different {_poline['UOM']} <> {_dict['UOM']}") + Error_msg = f"UOM different {_poline['UOM']} <> {_dict['UOM']}" + else: + # print("errorpoline <>DN") + Error_msg = f"poline[ItemFullName] <> DN[FullName]; {_poline['ItemFullName']} <> {_dict['FullName']}, maybe there are 2 same namefromtaco in QB" + else: + pass + # print(f"this refnum {_dict['RefNum']} have no QB PO Return Line") + Error_msg = f"this refnum {_dict['RefNum']} have no QB PO Return Line" + + # print (_bol_dictisadded, Error_msg) + return _bol_dictisadded, Error_msg + + + def prepareInvoice(self, df:pd.DataFrame = None): + # print(df) + _bolAllDNareOk = True + _notindflist=[] + _yescounter = 0 + _nocounter = 0 + if df is not None: + _dflist = df.to_dict('records') + # print(_dflist) + + # else: + # _dflist = self.dfDN.to_dict('records') + # print(self.dfDN) + # print(f'_dflist:{_dflist}') + for idx, xdf in enumerate(_dflist): + _boladdDN, _Errormsg = self.addDNQtyToInvoiceList(xdf) + # print(f'prepareInvoice->_Errormsg:{_Errormsg}') + if _boladdDN: + _dflist[idx]['ADDED']=True + elif _Errormsg: + _dflist[idx]['ERROR']=_Errormsg + for xdf in (_dflist): + if 'ADDED' not in xdf: + # print (f"prepareInvoice->not added: {xdf['Item No']}") + print (f"prepareInvoice->not added: {xdf}") + + _notindflist.append(xdf) + _nocounter+=1 + _bolAllDNareOk = False + else: + print (f"ADDED: {xdf['Item No']}") + + print(f'{len(_dflist) - _nocounter} of {len(_dflist)} are added') + return _bolAllDNareOk, _notindflist + + + def validate_date(self, date_text): + if date_text is None: + return None + try: + return datetime.datetime.strptime(date_text, '%Y-%m-%d').date() + except ValueError: + return None + # raise ValueError("Incorrect data format, should be YYYY-MM-DD") + + def get_ext_doc_no_list(self, dndict=None): + if dndict: + dnlist = dndict['lines'] + else: + 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]) + # print(df) + ext_doc_no=df['RefNum'].unique().tolist() + if len(ext_doc_no)>0: + return df, ext_doc_no + else: + return df, None + + + def get_last_refnumber(self, response_string=None): + if not response_string: + response_string = self.connect_to_quickbooks(self.create_QBXML()) + status, status_msg = self.status_ok(response_string) + if not status: + return None + QBXML = ET.fromstring(response_string) + _OpenInvoicelist = [] + InvoiceRets = QBXML.findall('.//RefNumber') + print(f'InvoiceRets count:{len(InvoiceRets)}') + refnumbers = [] + for InvoiceRet in InvoiceRets: + print(InvoiceRet, InvoiceRet.text) + refnumbers.append(InvoiceRet.text) + + # IsFullyInvoiced = InvoiceRet.find('IsFullyInvoiced').text + # IsManuallyClosed = InvoiceRet.find('IsManuallyClosed').text + # if IsFullyInvoiced=='false' and IsManuallyClosed=='false': + # txndate = InvoiceRet.find('TxnDate').text + # totalamount = InvoiceRet.find('TotalAmount').text + # refnumber = InvoiceRet.find('RefNumber').text + + # _OpenInvoicelist.append([InvoiceRet.find('TxnID').text, txndate, totalamount, refnumber, ]) + # # _OpenInvoicelist.append(InvoiceRet.find('TxnID').text) + # # RefNumber = InvoiceRet.find('RefNumber').text + # # Memo = InvoiceRet.find('Memo').text + # # CustomerFullName = InvoiceRet.find('CustomerRef/FullName').text + # # TxnID = InvoiceRet.find('TxnID').text + # # TotalAmount = InvoiceRet.find('TotalAmount').text + # # IsFullyReceived = InvoiceRet.find('IsFullyReceived').text + # # IsManuallyClosed = InvoiceRet.find('IsManuallyClosed').text + print(refnumbers) + refnumbers.sort() + return refnumbers[-1] + + def get_open_so(self, response_string=None): + if not response_string: + response_string = self.connect_to_quickbooks(self.create_QBXML()) + + QBXML = ET.fromstring(response_string) + _OpenInvoicelist = [] + InvoiceRets = QBXML.findall('.//InvoiceRet') + # print(f'InvoiceRets count:{len(InvoiceRets)}') + for InvoiceRet in InvoiceRets: + IsFullyInvoiced = InvoiceRet.find('IsFullyInvoiced').text + IsManuallyClosed = InvoiceRet.find('IsManuallyClosed').text + if IsFullyInvoiced=='false' and IsManuallyClosed=='false': + txndate = InvoiceRet.find('TxnDate').text + totalamount = InvoiceRet.find('TotalAmount').text + refnumber = InvoiceRet.find('RefNumber').text + + _OpenInvoicelist.append([InvoiceRet.find('TxnID').text, txndate, totalamount, refnumber, ]) + # _OpenInvoicelist.append(InvoiceRet.find('TxnID').text) + # RefNumber = InvoiceRet.find('RefNumber').text + # Memo = InvoiceRet.find('Memo').text + # CustomerFullName = InvoiceRet.find('CustomerRef/FullName').text + # TxnID = InvoiceRet.find('TxnID').text + # TotalAmount = InvoiceRet.find('TotalAmount').text + # IsFullyReceived = InvoiceRet.find('IsFullyReceived').text + # IsManuallyClosed = InvoiceRet.find('IsManuallyClosed').text + # print(_OpenInvoicelist) + return _OpenInvoicelist + + def create_open_sales_order_qbxml(self, txnid:list, IncludeLineItems=True): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + InvoiceQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "InvoiceQueryRq","\n " ) + if len(txnid)>0: + for x in txnid: + TxnID = self.create_sub_element(ET, InvoiceQueryRq, "TxnID", x, 6 ) + else: + return None + if IncludeLineItems: + IncludeLineItems = self.create_sub_element(ET, InvoiceQueryRq, "IncludeLineItems", 'true', 4) + # if len(self.IncludeRetElement)>0: + # for x in self.IncludeRetElement: + # IncludeRetElement = self.create_sub_element(ET, InvoiceQueryRq, "IncludeRetElement", x, 4) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + print(f'create_open_sale_order_qbxml->qbxml_query: {qbxml_query}') + return qbxml_query + + + def get_open_sales_order(self, txnlist:list): + print(f'txnid: {txnlist}', type(txnlist)) + txnid = [] + for x in txnlist: + if isinstance(x, list): + txnid.append(x[0]) + else: + txnid.append(x) + break + # txnid = [x[0] if isinstance(x, list) else x for x in txnid ] + print(txnid) + if txnid: + # print(self.connect_to_quickbooks(self.create_open_sales_order_qbxml(txnid))) + return self._get_sales_order_header(self.connect_to_quickbooks(self.create_open_sales_order_qbxml(txnid))) + else: + print("There is No Open Invoice Order") + return None + return None + +print('### InvoiceQuery ###') +if __name__ == '__main__': + starttime = timeit.default_timer() + # ini=InvoiceQuery(FullName= '999 HPL', IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'IsManuallyClosed', 'IsFullyInvoiced']) + + # ini=InvoiceQuery(FullName= 'YSM Interior', IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'TxnDate', 'RefNumber', 'IsManuallyClosed', 'IsFullyInvoiced','TotalAmount']) + ini=InvoiceQuery(FullName= 'Abadi Serpong', IncludeRetElement = 'RefNumber', ]) + # iya = ini.create_customerquery_QBXML() #pakai excel saja lebih cepat + # print(iya) + print(f'createQBXML:{ini.create_QBXML()}') + response_string = ini.connect_to_quickbooks(ini.create_QBXML()) + print(f'response_string:{response_string}') + # response_string = None + last_refnumber = ini.get_last_refnumber(response_string) + print(f'open sales orders:{last_refnumber};type:{type(last_refnumber)}') + # print('23a'+1) + # if open_sales_orders: + + # itu = ini.get_open_sales_order(open_sales_orders) + # # print(itu) + # print(f'get_open_sales_order:{itu}') + # if itu: + + # print(ini.create_invoiceadd_QBXML()) + + # # ini.connect_to_quickbooks(ini.create_invoiceadd_QBXML()) + + print("The time difference is :", timeit.default_timer() - starttime) \ No newline at end of file diff --git a/SO_to_Inv/PriceLevelQuery.py b/SO_to_Inv/PriceLevelQuery.py new file mode 100644 index 0000000..0f2d770 --- /dev/null +++ b/SO_to_Inv/PriceLevelQuery.py @@ -0,0 +1,444 @@ +import xml.etree.ElementTree as ET +import win32com.client +import xmltodict +import pprint +import datetime +import pandas as pd +from datetime import date +import timeit + +class PriceLevelQuery: + def __init__(self, **kwargs) -> None: + # print(f'kwargs:{kwargs}') + # print(args) + # self.SalesOrderList=[] + self.IncludeLineItems = kwargs['IncludeLineItems'] if 'IncludeLineItems' in kwargs else 'true' + self.IncludeRetElement = kwargs['IncludeRetElement'] if 'IncludeRetElement' in kwargs else [] + self.TxnDateRangeFilter = kwargs['TxnDateRangeFilter'] if 'TxnDateRangeFilter' in kwargs else None + self.FullName = kwargs['FullName'] if 'FullName' in kwargs and isinstance(kwargs['FullName'], list) else [] + self.NameFilter = kwargs['NameFilter'] if 'NameFilter' in kwargs else None + self.ItemRef = kwargs['ItemRef'] if 'ItemRef' in kwargs else None + + def create_sub_element(self, ET, parentNode, thisNode, text="\n", whiteSpace = 0, attrib =None): + if type(attrib) is not dict: + attrib = {} + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + def create_QBXML(self): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + PriceLevelQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "PriceLevelQueryRq","\n " ) + if len(self.FullName)>0: + for x in self.FullName: + FullName = self.create_sub_element(ET, PriceLevelQueryRq, "FullName", x, 6) + if self.NameFilter: + NameFilter = self.create_sub_element(ET, PriceLevelQueryRq, "NameFilter","\n ", 6) + MatchCriterion = self.create_sub_element(ET, NameFilter, "MatchCriterion", "StartsWith") + Name = self.create_sub_element(ET, NameFilter, "Name", self.NameFilter) + if self.ItemRef: + ItemRef = self.create_sub_element(ET, PriceLevelQueryRq, "ItemRef", "\n ") + ItemRefFullName = self.create_sub_element(ET, ItemRef, "FullName", self.ItemRef) + + if len(self.IncludeRetElement)>0: + for x in self.IncludeRetElement: + IncludeRetElement = self.create_sub_element(ET, PriceLevelQueryRq, "IncludeRetElement", x, 4) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + # print(f'create_QBXML->qbxml_query: {qbxml_query}') + return qbxml_query + + def create_invoiceadd_QBXML(self): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + InvoiceAddRq = self.create_sub_element(ET, QBXMLMsgsRq, "InvoiceAddRq", "\n ",2 ) + InvoiceAdd = self.create_sub_element(ET, InvoiceAddRq, "InvoiceAdd", "\n ",4 ) + CustomerRef = self.create_sub_element(ET, InvoiceAdd, "CustomerRef", "\n ",8 ) + FullName = self.create_sub_element(ET, CustomerRef, "FullName", self.SalesOrderList[1]['CustomerFullName'], 8 ) + TemplateRef = self.create_sub_element(ET, InvoiceAdd, "TemplateRef", "\n ", 8 ) + tempFullName = self.create_sub_element(ET, TemplateRef, "FullName", "DBW Invoice (11%)", 8 ) + today = str(date.today()) + TxnDate = self.create_sub_element(ET, InvoiceAdd, "TxnDate", today,8) # self.DN['TxnDate'], 8 ) + + RefNumber = self.create_sub_element(ET, InvoiceAdd, "RefNumber", today,8 ) # self.DN['DNRefNum'], 8 ) + ShipDate = self.create_sub_element(ET, InvoiceAdd, "ShipDate", today,8) # self.DN['TxnDate'], 8 ) + # Memo = self.create_sub_element(ET, InvoiceAdd, "Memo", self.DN['Memo'], 10 ) + disc_amount = 0 + for soidx, salesorder in enumerate(self.SalesOrderList): + SOTxnId = salesorder['TxnID'] + 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")}') + # 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") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + 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)}") + + return qbxml_query + + + def connect_to_quickbooks(self, qbxml_query): + # Connect to Quickbooks + # sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + # sessionManager.OpenConnection('', 'DASA') + # enumfodnc= win32com.client.Dispatch('QBXMLRP2.RequestProcessor') + # print(enumfodnc) + # print(enumfodnc.qbFileOpenDoNotCare) + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA2') + # ticket = sessionManager.BeginSession("z:\\DBW Bogor.qbw", 2) + + ticket = sessionManager.BeginSession("", 2) + + # Send query and receive response + response_string = sessionManager.ProcessRequest(ticket, qbxml_query) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + # print (f'response_string:{response_string}') + return response_string + + def __str__(self, *args) -> str: + # return str(self._get_datarow(self.connect_to_quickbooks(self.create_QBXML()))) + # print("__str__") + return str(self.get_sales_order_header()) + # return "hello" + + def get_sales_order_header(self, *args): + return self. _get_sales_order_header(self.connect_to_quickbooks(self.create_QBXML())) + + def status_ok(self, QBXML): #for InvoiceAddRS + + tree = ET.fromstring(QBXML) + + GSRQRs = tree.find(".//PriceLevelQueryRs") + # print(f"GSRQRs:{GSRQRs}") + status_code = GSRQRs.attrib #.get('statusCode') + # print(GSRQRs.attrib) + # print(GSRQRs.attrib['statusCode']) + status=GSRQRs.attrib.get('statusMessage') + + print(f'status={status}') + if 'OK' in status: + return True, status_code + else: + return False, status_code + + + def _get_sales_order_header(self, response_string): + print('_get_sales_order_header') + # print(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 + 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, + 'TotalAmount':TotalAmount, 'IsFullyInvoiced':IsFullyInvoiced, 'IsManuallyClosed':IsManuallyClosed, 'SalesOrderLineRet':[]} + SalesOrderLineRet = SalesOrderRet.findall('SalesOrderLineRet') + # print(len(SalesOrderLineRet)) + if len(SalesOrderLineRet) > 0: + disc_amount=0 + for SalesOrderLineRet in SalesOrderLineRet: + TxnLineID = SalesOrderLineRet.find('TxnLineID').text + ItemFullName = SalesOrderLineRet.find('ItemRef/FullName').text + Quantity = SalesOrderLineRet.find('Quantity').text + UnitOfMeasure = SalesOrderLineRet.find('UnitOfMeasure').text + Rate = float(SalesOrderLineRet.find('Rate').text) + + Amount = float(SalesOrderLineRet.find('Amount').text) + 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 addDiscountToInvoiceList(self, _dict:dict): + print("addDiscountToInvoiceList") + + + def addDNQtyToSalesOrderList(self, _dict:dict): + _bolfoundrefnum=False + _bol_dictisadded=False + Error_msg = None + for poidx, _po in enumerate(self.SalesOrderList): + if _po['RefNumber']==_dict['RefNum']: + _bolfoundrefnum=True + if len(_po['SalesOrderLineRet'])>0: + for polineidx, _poline in enumerate(_po['SalesOrderLineRet']): + pass + if _poline['ItemFullName']==_dict['FullName']: + if _poline['UOM'].upper()==_dict['UOM'].upper(): + # first do UOM in _dict convert treatment + QuantityIn_dict = _dict['Quantity'] + if _dict['UOM'].upper().startswith('ROLL_'): + print(f"addDNQtyToSalesOrderList->DNqty:{_dict['Quantity']}, Roll_:{_dict['UOM'].split('_')[1]}") + QuantityIn_dict = _dict['Quantity'] * int(_dict['UOM'].split("_")[1]) + pass + elif _dict['UOM'].upper() == 'BOX' and _dict['Item No'].upper() == "CUTTER": + print("addDNQtyToSalesOrderList->cutter") + elif _dict['UOM'].upper() == 'BOX' and (_dict['Item No'].upper().startswith("EB-") or _dict['Item No'].upper().startswith("TA-")): + print("addDNQtyToSalesOrderList->LEM") + if _dict['Item No'].split("-")[1].endswith("1006"): + QuantityIn_dict = QuantityIn_dict * 12 + elif _dict['Item No'].split("-")[1].endswith("1025"): + QuantityIn_dict = QuantityIn_dict * 6 + elif _dict['Item No'].split("-")[1].endswith("1100"): + pass + print("1100 lem") + elif _dict['UOM'].upper() == 'BOX' and (_dict['Item No'].upper().startswith("TL-") or _dict['Item No'].upper().startswith("TFL-")): + print("addDNQtyToSalesOrderList->Lock") + QuantityIn_dict = QuantityIn_dict * 20 + elif _dict['UOM'].upper() == 'BOX' and _dict['Item No'].upper() == "EDG-TRIMMER": + QuantityIn_dict = QuantityIn_dict * 12 #coz box of 12 + + + if _poline['BackOrdered']>=QuantityIn_dict: + self.SalesOrderList[poidx]['SalesOrderLineRet'][polineidx]['DNQuantity']=float(QuantityIn_dict) + _bol_dictisadded = True + else: + print(f"{_poline['ItemFullName']} BackOrdered < Qty in DN {_poline['BackOrdered']}<{QuantityIn_dict}") + Error_msg = f"BackOrdered < Qty in DN {_poline['BackOrdered']}<{QuantityIn_dict}" + else: + # print(f"UOM different {_poline['UOM']} <> {_dict['UOM']}") + Error_msg = f"UOM different {_poline['UOM']} <> {_dict['UOM']}" + else: + # print("errorpoline <>DN") + Error_msg = f"poline[ItemFullName] <> DN[FullName]; {_poline['ItemFullName']} <> {_dict['FullName']}, maybe there are 2 same namefromtaco in QB" + else: + pass + # print(f"this refnum {_dict['RefNum']} have no QB PO Return Line") + Error_msg = f"this refnum {_dict['RefNum']} have no QB PO Return Line" + + # print (_bol_dictisadded, Error_msg) + return _bol_dictisadded, Error_msg + + + def prepareInvoice(self, df:pd.DataFrame = None): + # print(df) + _bolAllDNareOk = True + _notindflist=[] + _yescounter = 0 + _nocounter = 0 + if df is not None: + _dflist = df.to_dict('records') + # print(_dflist) + + else: + _dflist = self.dfDN.to_dict('records') + # print(self.dfDN) + # print(f'_dflist:{_dflist}') + for idx, xdf in enumerate(_dflist): + _boladdDN, _Errormsg = self.addDNQtyToSalesOrderList(xdf) + # print(f'prepareInvoice->_Errormsg:{_Errormsg}') + if _boladdDN: + _dflist[idx]['ADDED']=True + elif _Errormsg: + _dflist[idx]['ERROR']=_Errormsg + for xdf in (_dflist): + if 'ADDED' not in xdf: + # print (f"prepareInvoice->not added: {xdf['Item No']}") + print (f"prepareInvoice->not added: {xdf}") + + _notindflist.append(xdf) + _nocounter+=1 + _bolAllDNareOk = False + else: + print (f"ADDED: {xdf['Item No']}") + + print(f'{len(_dflist) - _nocounter} of {len(_dflist)} are added') + return _bolAllDNareOk, _notindflist + + + def validate_date(self, date_text): + if date_text is None: + return None + try: + return datetime.datetime.strptime(date_text, '%Y-%m-%d').date() + except ValueError: + return None + # raise ValueError("Incorrect data format, should be YYYY-MM-DD") + + def get_ext_doc_no_list(self, dndict=None): + if dndict: + dnlist = dndict['lines'] + else: + 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]) + # print(df) + ext_doc_no=df['RefNum'].unique().tolist() + if len(ext_doc_no)>0: + return df, ext_doc_no + else: + return df, None + + def get_pricelevel(self, response_string=None): + if not response_string: + response_string = self.connect_to_quickbooks(self.create_QBXML()) + statusok, status = self.status_ok(response_string) + if statusok: + QBXML = ET.fromstring(response_string) + PriceLevellist = {} + fullnamelist = [] + custompricelist =[] + PriceLevelRets = QBXML.findall('.//PriceLevelRet') + PriceLevelNamelist = [] + # PriceLevelName = QBXML.find('.//Name').text + + # print(f'PriceLevelPerItemRets count:{len(PriceLevelPerItemRets)}') + for PriceLevelRet in PriceLevelRets: + PriceLevelPerItemRets = PriceLevelRet.findall('.//PriceLevelPerItemRet') + PriceLevelName = PriceLevelRet.find('.//Name').text + print(f'pricelevelname:{PriceLevelName}') + for PriceLevelPerItemRet in PriceLevelPerItemRets: + FullName = PriceLevelPerItemRet.find('.//FullName').text + fullnamelist.append(FullName) + CustomPrice = PriceLevelPerItemRet.find('CustomPrice').text + custompricelist.append(CustomPrice) + PriceLevelNamelist.append(PriceLevelName) + zip(fullnamelist, custompricelist) + PriceLevellist['PriceLevelName'] = PriceLevelNamelist + PriceLevellist['FullName']= fullnamelist + PriceLevellist['CustomPrice']= custompricelist + PriceLeveldf = pd.DataFrame.from_dict(PriceLevellist) + PriceLeveldf.sort_values(by=['PriceLevelName', 'FullName'], inplace=True) + PriceLeveldf=PriceLeveldf.reset_index(drop=True) + print(PriceLeveldf) + PriceLeveldf.to_excel('ItemInventory\PriceLevel.xlsx', sheet_name=PriceLevelName, index=False ) + # print(PriceLevellist) + return PriceLevellist + else: + return None + + def create_open_sales_order_qbxml(self, txnid:list, IncludeLineItems=True): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + SalesOrderQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "SalesOrderQueryRq","\n " ) + if len(txnid)>0: + for x in txnid: + TxnID = self.create_sub_element(ET, SalesOrderQueryRq, "TxnID", x, 6 ) + else: + return None + if IncludeLineItems: + IncludeLineItems = self.create_sub_element(ET, SalesOrderQueryRq, "IncludeLineItems", 'true', 4) + # if len(self.IncludeRetElement)>0: + # for x in self.IncludeRetElement: + # IncludeRetElement = self.create_sub_element(ET, SalesOrderQueryRq, "IncludeRetElement", x, 4) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + print(f'create_QBXML->qbxml_query: {qbxml_query}') + return qbxml_query + + + def get_open_sales_order(self, txnid:list): + print(f'txnid: {txnid}', type(txnid)) + txnid = [x[0] if isinstance(x, list) else x for x in txnid ] + if txnid: + # print(self.connect_to_quickbooks(self.create_open_sales_order_qbxml(txnid))) + return self._get_sales_order_header(self.connect_to_quickbooks(self.create_open_sales_order_qbxml(txnid))) + else: + print("There is No Open Sales Order") + return None + return None + +print('### PriceLevelQuery ###') +if __name__ == '__main__': + starttime = timeit.default_timer() + # ini=PriceLevelQuery(FullName= '999 HPL', IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'IsManuallyClosed', 'IsFullyInvoiced']) + # ini=PriceLevelQuery(FullName= 'abadi serpong', IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'TxnDate', 'RefNumber', 'IsManuallyClosed', 'IsFullyInvoiced','TotalAmount']) + ini = PriceLevelQuery(FullName = ['t 202202', 'M 202202'], ) + # ini = PriceLevelQuery( ItemRef="ECO:0:ECO-002") + itu = ini.create_QBXML() + print(f'createQBXML->main:{itu}') + response_string = ini.connect_to_quickbooks(itu) + print(f'response_string:{response_string}') + response_string = None + pricelevel = ini.get_pricelevel() + # print(f'pricelevel:{pricelevel}') + + # print(ini.get_open_sales_order(open_sales_orders)) + + # print(ini.create_invoiceadd_QBXML()) + # ini.connect_to_quickbooks(ini.create_invoiceadd_QBXML()) + + print("The time difference is :", timeit.default_timer() - starttime) \ No newline at end of file diff --git a/SO_to_Inv/SalesOrderQuery.xml b/SO_to_Inv/SalesOrderQuery.xml new file mode 100644 index 0000000..df87a04 --- /dev/null +++ b/SO_to_Inv/SalesOrderQuery.xml @@ -0,0 +1,336 @@ + + + + + + + IDTYPE + + STRTYPE + + STRTYPE + + INTTYPE + + + DATETIMETYPE + DATETIMETYPE + + + + + DATETYPE + DATETYPE + + + ENUMTYPE + + + + + + IDTYPE + + STRTYPE + + IDTYPE + + STRTYPE + + + + + + ENUMTYPE + STRTYPE + + + + STRTYPE + STRTYPE + + + + + IDTYPE + + STRTYPE + + + + BOOLTYPE + BOOLTYPE + STRTYPE + GUIDTYPE + + + + + IDTYPE + DATETIMETYPE + DATETIMETYPE + STRTYPE + INTTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + DATETYPE + STRTYPE + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + STRTYPE + + IDTYPE + STRTYPE + + DATETYPE + + IDTYPE + STRTYPE + + STRTYPE + DATETYPE + + IDTYPE + STRTYPE + + AMTTYPE + + IDTYPE + STRTYPE + + PERCENTTYPE + AMTTYPE + AMTTYPE + + IDTYPE + STRTYPE + + FLOATTYPE + AMTTYPE + BOOLTYPE + BOOLTYPE + STRTYPE + + IDTYPE + STRTYPE + + BOOLTYPE + BOOLTYPE + BOOLTYPE + + IDTYPE + STRTYPE + + STRTYPE + GUIDTYPE + + IDTYPE + + ENUMTYPE + DATETYPE + STRTYPE + + ENUMTYPE + AMTTYPE + + + + IDTYPE + + IDTYPE + STRTYPE + + STRTYPE + QUANTYPE + STRTYPE + + IDTYPE + STRTYPE + + + PRICETYPE + + PERCENTTYPE + + + IDTYPE + STRTYPE + + AMTTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + STRTYPE + + STRTYPE + + STRTYPE + + IDTYPE + STRTYPE + + QUANTYPE + BOOLTYPE + STRTYPE + STRTYPE + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + + IDTYPE + + IDTYPE + STRTYPE + + STRTYPE + QUANTYPE + STRTYPE + + IDTYPE + STRTYPE + + BOOLTYPE + AMTTYPE + + IDTYPE + + IDTYPE + STRTYPE + + STRTYPE + QUANTYPE + STRTYPE + + IDTYPE + STRTYPE + + + PRICETYPE + + PERCENTTYPE + + + IDTYPE + STRTYPE + + AMTTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + STRTYPE + + STRTYPE + + STRTYPE + + IDTYPE + STRTYPE + + QUANTYPE + BOOLTYPE + STRTYPE + STRTYPE + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + ENUMTYPE + + + IDTYPE + STRTYPE + STRTYPE + AMTTYPE + + + ENUMTYPE + STRTYPE + STRTYPE + + + + diff --git a/SO_to_Inv/__init__.py b/SO_to_Inv/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/SO_to_Inv/invoiceadd.py b/SO_to_Inv/invoiceadd.py new file mode 100644 index 0000000..9b5650b --- /dev/null +++ b/SO_to_Inv/invoiceadd.py @@ -0,0 +1,417 @@ +import xml.etree.ElementTree as ET +import win32com.client +import xmltodict +import pprint +import datetime +import pandas as pd +from datetime import date +import timeit + +class SalesOrderQuery: + def __init__(self, **kwargs) -> None: + # print(f'kwargs:{kwargs}') + # print(args) + # self.SalesOrderList=[] + self.DN = kwargs['DN'] if 'DN' in kwargs else {} + self.Reuse = kwargs['Reuse'] if 'Reuse' in kwargs else None + + self.SalesOrderList= kwargs['SalesOrderList'] if 'SalesOrderList' in kwargs else [] + + self.SalesOrderType = kwargs['SalesOrderType'] if 'SalesOrderType' in kwargs else 'SalesByCustomerSummary' + self.IncludeLineItems = kwargs['IncludeLineItems'] if 'IncludeLineItems' in kwargs else 'true' + self.IncludeRetElement = kwargs['IncludeRetElement'] if 'IncludeRetElement' in kwargs else [] + self.TxnDateRangeFilter = kwargs['TxnDateRangeFilter'] if 'TxnDateRangeFilter' in kwargs else None + self.DateMacro = None + if 'DateMacro' in kwargs: + if kwargs['DateMacro'] in ['All', 'Today', 'ThisWeek', 'ThisWeekToDate', 'ThisMonth', 'ThisMonthToDate', 'ThisQuarter', 'ThisQuarterToDate', 'ThisYear', 'ThisYearToDate', 'Yesterday', 'LastWeek', 'LastWeekToDate', 'LastMonth', 'LastMonthToDate', 'LastQuarter', 'LastQuarterToDate', 'LastYear', 'LastYearToDate', 'NextWeek', 'NextFourWeeks', 'NextMonth', 'NextQuarter', 'NextYear']: + self.DateMacro = kwargs['DateMacro'] + self.FromTxnDate = self.validate_date(kwargs['FromTxnDate']) if 'FromTxnDate' in kwargs else None + self.ToTxnDate = self.validate_date(kwargs['ToTxnDate']) if 'ToTxnDate' in kwargs else None + self.ReportEntityFilter = kwargs['ReportEntityFilter'] if 'ReportEntityFilter' in kwargs else None + self.FullName = kwargs['FullName'] if 'FullName' in kwargs else None + # print(self.DateMacro, self.TxnDateRangeFilter, self.FromTxnDate, self.ToTxnDate) + # 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.get_sales_order_header() + + def create_sub_element(self, ET, parentNode, thisNode, text="\n", whiteSpace = 0, attrib =None): + if type(attrib) is not dict: + attrib = {} + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + def create_QBXML(self): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + 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: + EntityFilter = self.create_sub_element(ET, SalesOrderQueryRq, 'EntityFilter', "\n ") + FullName = self.create_sub_element(ET, EntityFilter, "FullName", self.FullName, 6) + # print(f'refnumber:{self.RefNumber}') + # if self.RefNumber: + # for rn in self.RefNumber: + # RefNumber = self.create_sub_element(ET, SalesOrderQueryRq, "RefNumber", f'{rn}', 4) + if 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) + + elif type(self.FromTxnDate) is datetime.date or type(self.ToTxnDate) is datetime.date: + TxnDateRangeFilter = self.create_sub_element(ET, SalesOrderQueryRq, "TxnDateRangeFilter", "\n ",) + if type(self.FromTxnDate) is datetime.date: + FromTxnDate = self.create_sub_element(ET, TxnDateRangeFilter, "FromTxnDate", self.FromTxnDate.strftime('%Y-%m-%d'),4) + if type(self.ToTxnDate) is datetime.date: + ToTxnDate = self.create_sub_element(ET, TxnDateRangeFilter, "ToTxnDate", self.ToTxnDate.strftime('%Y-%m-%d')) + if self.IncludeLineItems: + IncludeLineItems = self.create_sub_element(ET, SalesOrderQueryRq, "IncludeLineItems", self.IncludeLineItems, 4) + if len(self.IncludeRetElement)>0: + for x in self.IncludeRetElement: + IncludeRetElement = self.create_sub_element(ET, SalesOrderQueryRq, "IncludeRetElement", x, 4) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + print(f'create_QBXML->qbxml_query: {qbxml_query}') + return qbxml_query + + def create_invoiceadd_QBXML(self): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + InvoiceAddRq = self.create_sub_element(ET, QBXMLMsgsRq, "InvoiceAddRq", "\n ",2 ) + InvoiceAdd = self.create_sub_element(ET, InvoiceAddRq, "InvoiceAdd", "\n ",4 ) + CustomerRef = self.create_sub_element(ET, InvoiceAdd, "CustomerRef", "\n ",8 ) + FullName = self.create_sub_element(ET, CustomerRef, "FullName", "TACO", 8 ) + today = str(date.today()) + TxnDate = self.create_sub_element(ET, InvoiceAdd, "TxnDate", self.DN['TxnDate'], 8 ) + RefNumber = self.create_sub_element(ET, InvoiceAdd, "RefNumber", self.DN['DNRefNum'], 8 ) + Memo = self.create_sub_element(ET, InvoiceAdd, "Memo", self.DN['Memo'], 10 ) + for salesorder in self.SalesOrderList: + POTxnId = salesorder['TxnID'] + print(f'create_invoiceadd_QBXML->POTxnID: {POTxnId}') + for itemline in salesorder['SalesOrderLineRet']: + if 'DNQuantity' in itemline: + ItemLineAdd = self.create_sub_element(ET, InvoiceAdd, "ItemLineAdd", "\n ", 10 ) + Quantity = self.create_sub_element(ET, ItemLineAdd, "Quantity", str(itemline['DNQuantity'] ), 12 ) + UnitOfMeasure = self.create_sub_element(ET, ItemLineAdd, "UnitOfMeasure", str(itemline['UOM']), 12 ) + LinkToTxn = self.create_sub_element(ET, ItemLineAdd, "LinkToTxn", "\n ",10 ) + TxnID = self.create_sub_element(ET, LinkToTxn, "TxnID", POTxnId,14 ) + TxnLineID = self.create_sub_element(ET, LinkToTxn, "TxnLineID", itemline['TxnLineID'],12 ) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + 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)}") + + return qbxml_query + + + def connect_to_quickbooks(self, qbxml_query): + # Connect to Quickbooks + # sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + # sessionManager.OpenConnection('', 'DASA') + # enumfodnc= win32com.client.Dispatch('QBXMLRP2.RequestProcessor') + # print(enumfodnc) + # print(enumfodnc.qbFileOpenDoNotCare) + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA2') + # ticket = sessionManager.BeginSession("z:\\DBW Bogor.qbw", 2) + + ticket = sessionManager.BeginSession("", 2) + + # Send query and receive response + response_string = sessionManager.ProcessRequest(ticket, qbxml_query) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + print (response_string) + return response_string + + def __str__(self, *args) -> str: + # return str(self._get_datarow(self.connect_to_quickbooks(self.create_QBXML()))) + # print("__str__") + return str(self.get_sales_order_header()) + # return "hello" + + def get_sales_order_header(self, *args): + return self. _get_sales_order_header(self.connect_to_quickbooks(self.create_QBXML())) + + def status_ok(self, QBXML): #for InvoiceAddRS + + tree = ET.fromstring(QBXML) + + GSRQRs = tree.find(".//InvoiceAddRs") + # print(f"GSRQRs:{GSRQRs}") + status_code = GSRQRs.attrib #.get('statusCode') + # print(GSRQRs.attrib) + # print(GSRQRs.attrib['statusCode']) + status=GSRQRs.attrib.get('statusMessage') + + print(f'status={status}') + if 'OK' in status: + return True, status_code + else: + return False, status_code + + + def _get_sales_order_header(self, response_string): + print('_get_sales_order_header') + # print(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 + 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, + 'TotalAmount':TotalAmount, 'IsFullyInvoiced':IsFullyInvoiced, 'IsManuallyClosed':IsManuallyClosed, 'SalesOrderLineRet':[]} + SalesOrderLineRet = SalesOrderRet.findall('SalesOrderLineRet') + # print(len(SalesOrderLineRet)) + if len(SalesOrderLineRet) > 0: + for SalesOrderLineRet in SalesOrderLineRet: + pass + TxnLineID = SalesOrderLineRet.find('TxnLineID').text + ItemFullName = SalesOrderLineRet.find('ItemRef/FullName').text + Quantity = SalesOrderLineRet.find('Quantity').text + UnitOfMeasure = SalesOrderLineRet.find('UnitOfMeasure').text + Rate = float(SalesOrderLineRet.find('Rate').text) + Amount = float(SalesOrderLineRet.find('Amount').text) + Invoiced = SalesOrderLineRet.find('Invoiced').text + # IsBilled = SalesOrderLineRet.find('IsBilled').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, + # 'IsBilled':IsBilled, + 'LineIsManuallyClosed':LineIsManuallyClosed, + } + SalesOrderdict['SalesOrderLineRet'].append(SalesOrderLinedict) + _SalesOrderlist.append(SalesOrderdict) + # print(_SalesOrderlist) + self.SalesOrderList=_SalesOrderlist + print(f'_get_sales_order_header->Salesorderlist: {self.SalesOrderList}') + # return SalesOrderlist + + def addDNQtyToSalesOrderList(self, _dict:dict): + _bolfoundrefnum=False + _bol_dictisadded=False + Error_msg = None + for poidx, _po in enumerate(self.SalesOrderList): + if _po['RefNumber']==_dict['RefNum']: + _bolfoundrefnum=True + if len(_po['SalesOrderLineRet'])>0: + for polineidx, _poline in enumerate(_po['SalesOrderLineRet']): + pass + if _poline['ItemFullName']==_dict['FullName']: + if _poline['UOM'].upper()==_dict['UOM'].upper(): + # first do UOM in _dict convert treatment + QuantityIn_dict = _dict['Quantity'] + if _dict['UOM'].upper().startswith('ROLL_'): + print(f"addDNQtyToSalesOrderList->DNqty:{_dict['Quantity']}, Roll_:{_dict['UOM'].split('_')[1]}") + QuantityIn_dict = _dict['Quantity'] * int(_dict['UOM'].split("_")[1]) + pass + elif _dict['UOM'].upper() == 'BOX' and _dict['Item No'].upper() == "CUTTER": + print("addDNQtyToSalesOrderList->cutter") + elif _dict['UOM'].upper() == 'BOX' and (_dict['Item No'].upper().startswith("EB-") or _dict['Item No'].upper().startswith("TA-")): + print("addDNQtyToSalesOrderList->LEM") + if _dict['Item No'].split("-")[1].endswith("1006"): + QuantityIn_dict = QuantityIn_dict * 12 + elif _dict['Item No'].split("-")[1].endswith("1025"): + QuantityIn_dict = QuantityIn_dict * 6 + elif _dict['Item No'].split("-")[1].endswith("1100"): + pass + print("1100 lem") + elif _dict['UOM'].upper() == 'BOX' and (_dict['Item No'].upper().startswith("TL-") or _dict['Item No'].upper().startswith("TFL-")): + print("addDNQtyToSalesOrderList->Lock") + QuantityIn_dict = QuantityIn_dict * 20 + elif _dict['UOM'].upper() == 'BOX' and _dict['Item No'].upper() == "EDG-TRIMMER": + QuantityIn_dict = QuantityIn_dict * 12 #coz box of 12 + + + if _poline['BackOrdered']>=QuantityIn_dict: + self.SalesOrderList[poidx]['SalesOrderLineRet'][polineidx]['DNQuantity']=float(QuantityIn_dict) + _bol_dictisadded = True + else: + print(f"{_poline['ItemFullName']} BackOrdered < Qty in DN {_poline['BackOrdered']}<{QuantityIn_dict}") + Error_msg = f"BackOrdered < Qty in DN {_poline['BackOrdered']}<{QuantityIn_dict}" + else: + # print(f"UOM different {_poline['UOM']} <> {_dict['UOM']}") + Error_msg = f"UOM different {_poline['UOM']} <> {_dict['UOM']}" + else: + # print("errorpoline <>DN") + Error_msg = f"poline[ItemFullName] <> DN[FullName]; {_poline['ItemFullName']} <> {_dict['FullName']}, maybe there are 2 same namefromtaco in QB" + else: + pass + # print(f"this refnum {_dict['RefNum']} have no QB PO Return Line") + Error_msg = f"this refnum {_dict['RefNum']} have no QB PO Return Line" + + # print (_bol_dictisadded, Error_msg) + return _bol_dictisadded, Error_msg + + + def prepareInvoice(self, df:pd.DataFrame = None): + # print(df) + _bolAllDNareOk = True + _notindflist=[] + _yescounter = 0 + _nocounter = 0 + if df is not None: + _dflist = df.to_dict('records') + # print(_dflist) + + else: + _dflist = self.dfDN.to_dict('records') + # print(self.dfDN) + # print(f'_dflist:{_dflist}') + for idx, xdf in enumerate(_dflist): + _boladdDN, _Errormsg = self.addDNQtyToSalesOrderList(xdf) + # print(f'prepareInvoice->_Errormsg:{_Errormsg}') + if _boladdDN: + _dflist[idx]['ADDED']=True + elif _Errormsg: + _dflist[idx]['ERROR']=_Errormsg + for xdf in (_dflist): + if 'ADDED' not in xdf: + # print (f"prepareInvoice->not added: {xdf['Item No']}") + print (f"prepareInvoice->not added: {xdf}") + + _notindflist.append(xdf) + _nocounter+=1 + _bolAllDNareOk = False + else: + print (f"ADDED: {xdf['Item No']}") + + print(f'{len(_dflist) - _nocounter} of {len(_dflist)} are added') + return _bolAllDNareOk, _notindflist + + + def validate_date(self, date_text): + if date_text is None: + return None + try: + return datetime.datetime.strptime(date_text, '%Y-%m-%d').date() + except ValueError: + return None + # raise ValueError("Incorrect data format, should be YYYY-MM-DD") + + def get_ext_doc_no_list(self, dndict=None): + if dndict: + dnlist = dndict['lines'] + else: + 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]) + # print(df) + ext_doc_no=df['RefNum'].unique().tolist() + if len(ext_doc_no)>0: + return df, ext_doc_no + else: + return df, None + + def get_open_so(self, response_string): + QBXML = ET.fromstring(response_string) + _OpenSalesOrderlist = [] + SalesOrderRets = QBXML.findall('.//SalesOrderRet') + # print(f'SalesOrderRets count:{len(SalesOrderRets)}') + for SalesOrderRet in SalesOrderRets: + IsFullyInvoiced = SalesOrderRet.find('IsFullyInvoiced').text + IsManuallyClosed = SalesOrderRet.find('IsManuallyClosed').text + if IsFullyInvoiced=='false' and IsManuallyClosed=='false': + _OpenSalesOrderlist.append(SalesOrderRet.find('TxnID').text) + # RefNumber = SalesOrderRet.find('RefNumber').text + # Memo = SalesOrderRet.find('Memo').text + # CustomerFullName = SalesOrderRet.find('CustomerRef/FullName').text + # TxnID = SalesOrderRet.find('TxnID').text + # TotalAmount = SalesOrderRet.find('TotalAmount').text + # IsFullyReceived = SalesOrderRet.find('IsFullyReceived').text + # IsManuallyClosed = SalesOrderRet.find('IsManuallyClosed').text + # print(_OpenSalesOrderlist) + return _OpenSalesOrderlist + + def create_open_sales_order_qbxml(self, txnid:list, IncludeLineItems=True): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + SalesOrderQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "SalesOrderQueryRq","\n " ) + if len(txnid)>0: + for x in txnid: + TxnID = self.create_sub_element(ET, SalesOrderQueryRq, "TxnID", x, 6 ) + else: + return None + if IncludeLineItems: + IncludeLineItems = self.create_sub_element(ET, SalesOrderQueryRq, "IncludeLineItems", 'true', 4) + # if len(self.IncludeRetElement)>0: + # for x in self.IncludeRetElement: + # IncludeRetElement = self.create_sub_element(ET, SalesOrderQueryRq, "IncludeRetElement", x, 4) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + print(f'create_QBXML->qbxml_query: {qbxml_query}') + return qbxml_query + + + def get_open_sales_order(self, txnid:list): + print(txnid, type(txnid)) + print(self.connect_to_quickbooks(self.create_open_sales_order_qbxml(txnid))) + self._get_sales_order_header(self.connect_to_quickbooks(self.create_open_sales_order_qbxml(txnid))) + +print('### SalesOrder ###') +if __name__ == '__main__': + starttime = timeit.default_timer() + ini=SalesOrderQuery(FullName= '999 HPL', IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'IsManuallyClosed', 'IsFullyInvoiced']) + print(ini.create_QBXML()) + response_string = ini.connect_to_quickbooks(ini.create_QBXML()) + open_sales_orders = ini.get_open_so(response_string) + print(open_sales_orders) + print(ini.get_open_sales_order(open_sales_orders)) + + print("The time difference is :", timeit.default_timer() - starttime) \ No newline at end of file diff --git a/SO_to_Inv/readSO.py b/SO_to_Inv/readSO.py new file mode 100644 index 0000000..a1e1c65 --- /dev/null +++ b/SO_to_Inv/readSO.py @@ -0,0 +1,544 @@ +import xml.etree.ElementTree as ET +import win32com.client +import xmltodict +import pprint +import datetime +import pandas as pd +from datetime import date +import timeit +import os + +class SalesOrderQuery: + def __init__(self, **kwargs) -> None: + # print(f'kwargs:{kwargs}') + # print(args) + # self.SalesOrderList=[] + self.PriceLevelName = None + self.SPPriceLevelName = None + self.cwd = kwargs['cwd'] if 'cwd' in kwargs else os.getcwd() + self.item_inventory_path = "ItemInventory" + self.price_level_filename = "PriceLevel.xlsx" + 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])) + self.FullName = kwargs['FullName'] if 'FullName' in kwargs else None + + self.CustomerPriceLevelName_filename = "CustomerList.xlsx" + 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.DN = kwargs['DN'] if 'DN' in kwargs else {} + self.Reuse = kwargs['Reuse'] if 'Reuse' in kwargs else None + + self.SalesOrderList= kwargs['SalesOrderList'] if 'SalesOrderList' in kwargs else [] + self.InvoiceList = None + self.SalesOrderType = kwargs['SalesOrderType'] if 'SalesOrderType' in kwargs else 'SalesByCustomerSummary' + self.IncludeLineItems = kwargs['IncludeLineItems'] if 'IncludeLineItems' in kwargs else 'true' + self.IncludeRetElement = kwargs['IncludeRetElement'] if 'IncludeRetElement' in kwargs else [] + self.TxnDateRangeFilter = kwargs['TxnDateRangeFilter'] if 'TxnDateRangeFilter' in kwargs else None + self.DateMacro = None + if 'DateMacro' in kwargs: + if kwargs['DateMacro'] in ['All', 'Today', 'ThisWeek', 'ThisWeekToDate', 'ThisMonth', 'ThisMonthToDate', 'ThisQuarter', 'ThisQuarterToDate', 'ThisYear', 'ThisYearToDate', 'Yesterday', 'LastWeek', 'LastWeekToDate', 'LastMonth', 'LastMonthToDate', 'LastQuarter', 'LastQuarterToDate', 'LastYear', 'LastYearToDate', 'NextWeek', 'NextFourWeeks', 'NextMonth', 'NextQuarter', 'NextYear']: + self.DateMacro = kwargs['DateMacro'] + self.FromTxnDate = self.validate_date(kwargs['FromTxnDate']) if 'FromTxnDate' in kwargs else None + self.ToTxnDate = self.validate_date(kwargs['ToTxnDate']) if 'ToTxnDate' in kwargs else None + self.ReportEntityFilter = kwargs['ReportEntityFilter'] if 'ReportEntityFilter' in kwargs else None + + # print(self.DateMacro, self.TxnDateRangeFilter, self.FromTxnDate, self.ToTxnDate) + # 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.get_sales_order_header() + + def create_sub_element(self, ET, parentNode, thisNode, text="\n", whiteSpace = 0, attrib =None): + if type(attrib) is not dict: + attrib = {} + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + def create_QBXML(self): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + 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: + EntityFilter = self.create_sub_element(ET, SalesOrderQueryRq, 'EntityFilter', "\n ") + FullName = self.create_sub_element(ET, EntityFilter, "FullName", self.FullName, 6) + if 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) + + elif type(self.FromTxnDate) is datetime.date or type(self.ToTxnDate) is datetime.date: + TxnDateRangeFilter = self.create_sub_element(ET, SalesOrderQueryRq, "TxnDateRangeFilter", "\n ",) + if type(self.FromTxnDate) is datetime.date: + FromTxnDate = self.create_sub_element(ET, TxnDateRangeFilter, "FromTxnDate", self.FromTxnDate.strftime('%Y-%m-%d'),4) + if type(self.ToTxnDate) is datetime.date: + ToTxnDate = self.create_sub_element(ET, TxnDateRangeFilter, "ToTxnDate", self.ToTxnDate.strftime('%Y-%m-%d')) + if self.IncludeLineItems: + IncludeLineItems = self.create_sub_element(ET, SalesOrderQueryRq, "IncludeLineItems", self.IncludeLineItems, 4) + if len(self.IncludeRetElement)>0: + for x in self.IncludeRetElement: + IncludeRetElement = self.create_sub_element(ET, SalesOrderQueryRq, "IncludeRetElement", x, 4) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + # print(f'create_QBXML->qbxml_query: {qbxml_query}') + return qbxml_query + + def get_customer_pricelevel(self, response_string): + QBXML = ET.fromstring(response_string) + PriceLevelName = QBXML.find('.//PriceLevelRef') + if PriceLevelName: + + PriceLevelName = PriceLevelName.find("FullName").text + print(f'PriceLevelName:{PriceLevelName}') + DataExtRets = QBXML.findall('.//DataExtRet') + SP_PriceLevelName = None + if len(DataExtRets)>0: + for DataExtRet in DataExtRets: + DataExtName = DataExtRet.find('DataExtName').text + DataExtValue = DataExtRet.find('DataExtValue').text + if DataExtName.lower() == 'special cust'.lower(): + SP_PriceLevelName = DataExtValue.upper() + break + self.PriceLevelName = PriceLevelName + self.SPPriceLevelName = SP_PriceLevelName + return PriceLevelName, SP_PriceLevelName + + def create_customerquery_QBXML(self ): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + CustomerQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "CustomerQueryRq","\n " ) + # SalesOrderType = self.create_sub_element(ET, CustomerQueryRq, 'SalesOrderType', self.SalesOrderType) + FullName = self.create_sub_element(ET, CustomerQueryRq, "FullName", self.FullName, 6) + IncludeRetElement = ['FullName', 'PriceLevelRef', 'DataExtRet'] + for x in IncludeRetElement: + IncludeRetElement = self.create_sub_element(ET, CustomerQueryRq, "IncludeRetElement", x, 4) + OwnerID = self.create_sub_element(ET, CustomerQueryRq, "OwnerID", "0", 6) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + print(f'create_customer_QBXML->qbxml_query: {qbxml_query}') + response_string=self.connect_to_quickbooks(qbxml_query) + + return self.get_customer_pricelevel(response_string) + return response_string + + def create_invoiceadd_QBXML(self): + print('create_ionvoiceadd_QBXML') + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + InvoiceAddRq = self.create_sub_element(ET, QBXMLMsgsRq, "InvoiceAddRq", "\n ",2 ) + InvoiceAdd = self.create_sub_element(ET, InvoiceAddRq, "InvoiceAdd", "\n ",4 ) + CustomerRef = self.create_sub_element(ET, InvoiceAdd, "CustomerRef", "\n ",8 ) + FullName = self.create_sub_element(ET, CustomerRef, "FullName", self.SalesOrderList[0]['CustomerFullName'], 8 ) + TemplateRef = self.create_sub_element(ET, InvoiceAdd, "TemplateRef", "\n ", 8 ) + TemplateFullName = self.create_sub_element(ET, TemplateRef, "FullName", "DBW Invoice (11%)", 8 ) + today = str(date.today()) + TxnDate = self.create_sub_element(ET, InvoiceAdd, "TxnDate", today,8) # self.DN['TxnDate'], 8 ) + + RefNumber = self.create_sub_element(ET, InvoiceAdd, "RefNumber", today,8 ) # self.DN['DNRefNum'], 8 ) + ShipDate = self.create_sub_element(ET, InvoiceAdd, "ShipDate", today,8) # self.DN['TxnDate'], 8 ) + # Memo = self.create_sub_element(ET, InvoiceAdd, "Memo", self.DN['Memo'], 10 ) + disc_amount = 0 + for soidx, salesorder in enumerate(self.SalesOrderList): + SOTxnId = salesorder['TxnID'] + 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") + 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") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + 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)}") + + return qbxml_query + + + def connect_to_quickbooks(self, qbxml_query): + # Connect to Quickbooks + # sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + # sessionManager.OpenConnection('', 'DASA') + # enumfodnc= win32com.client.Dispatch('QBXMLRP2.RequestProcessor') + # print(enumfodnc) + # print(enumfodnc.qbFileOpenDoNotCare) + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA2') + # ticket = sessionManager.BeginSession("z:\\DBW Bogor.qbw", 2) + + ticket = sessionManager.BeginSession("", 2) + + # Send query and receive response + response_string = sessionManager.ProcessRequest(ticket, qbxml_query) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + # print (f'response_string:{response_string}') + return response_string + + def __str__(self, *args) -> str: + # return str(self._get_datarow(self.connect_to_quickbooks(self.create_QBXML()))) + # print("__str__") + return str(self.get_sales_order_header()) + # return "hello" + + def get_sales_order_header(self, *args): + return self._get_sales_order_header(self.connect_to_quickbooks(self.create_QBXML())) + + def status_ok(self, QBXML): #for InvoiceAddRS + + tree = ET.fromstring(QBXML) + + GSRQRs = tree.find(".//InvoiceAddRs") + # print(f"GSRQRs:{GSRQRs}") + status_code = GSRQRs.attrib #.get('statusCode') + # print(GSRQRs.attrib) + # print(GSRQRs.attrib['statusCode']) + status=GSRQRs.attrib.get('statusMessage') + + print(f'status={status}') + if 'OK' in status: + return True, status_code + else: + return False, status_code + + + def _get_sales_order_header(self, response_string): + print('_get_sales_order_header') + # print(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 + 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, + 'TotalAmount':TotalAmount, 'IsFullyInvoiced':IsFullyInvoiced, 'IsManuallyClosed':IsManuallyClosed, 'SalesOrderLineRet':[]} + SalesOrderLineRet = SalesOrderRet.findall('SalesOrderLineRet') + # print(len(SalesOrderLineRet)) + if len(SalesOrderLineRet) > 0: + disc_amount=0 + for SalesOrderLineRet in SalesOrderLineRet: + TxnLineID = SalesOrderLineRet.find('TxnLineID').text + ItemFullName = SalesOrderLineRet.find('ItemRef/FullName').text + 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])) + 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])) + 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 addDiscountToInvoiceList(self, _dict:dict): + print("addDiscountToInvoiceList") + + + def addDNQtyToSalesOrderList(self, _dict:dict): + _bolfoundrefnum=False + _bol_dictisadded=False + Error_msg = None + for poidx, _po in enumerate(self.SalesOrderList): + if _po['RefNumber']==_dict['RefNum']: + _bolfoundrefnum=True + if len(_po['SalesOrderLineRet'])>0: + for polineidx, _poline in enumerate(_po['SalesOrderLineRet']): + pass + if _poline['ItemFullName']==_dict['FullName']: + if _poline['UOM'].upper()==_dict['UOM'].upper(): + # first do UOM in _dict convert treatment + QuantityIn_dict = _dict['Quantity'] + if _dict['UOM'].upper().startswith('ROLL_'): + print(f"addDNQtyToSalesOrderList->DNqty:{_dict['Quantity']}, Roll_:{_dict['UOM'].split('_')[1]}") + QuantityIn_dict = _dict['Quantity'] * int(_dict['UOM'].split("_")[1]) + pass + elif _dict['UOM'].upper() == 'BOX' and _dict['Item No'].upper() == "CUTTER": + print("addDNQtyToSalesOrderList->cutter") + elif _dict['UOM'].upper() == 'BOX' and (_dict['Item No'].upper().startswith("EB-") or _dict['Item No'].upper().startswith("TA-")): + print("addDNQtyToSalesOrderList->LEM") + if _dict['Item No'].split("-")[1].endswith("1006"): + QuantityIn_dict = QuantityIn_dict * 12 + elif _dict['Item No'].split("-")[1].endswith("1025"): + QuantityIn_dict = QuantityIn_dict * 6 + elif _dict['Item No'].split("-")[1].endswith("1100"): + pass + print("1100 lem") + elif _dict['UOM'].upper() == 'BOX' and (_dict['Item No'].upper().startswith("TL-") or _dict['Item No'].upper().startswith("TFL-")): + print("addDNQtyToSalesOrderList->Lock") + QuantityIn_dict = QuantityIn_dict * 20 + elif _dict['UOM'].upper() == 'BOX' and _dict['Item No'].upper() == "EDG-TRIMMER": + QuantityIn_dict = QuantityIn_dict * 12 #coz box of 12 + + + if _poline['BackOrdered']>=QuantityIn_dict: + self.SalesOrderList[poidx]['SalesOrderLineRet'][polineidx]['DNQuantity']=float(QuantityIn_dict) + _bol_dictisadded = True + else: + print(f"{_poline['ItemFullName']} BackOrdered < Qty in DN {_poline['BackOrdered']}<{QuantityIn_dict}") + Error_msg = f"BackOrdered < Qty in DN {_poline['BackOrdered']}<{QuantityIn_dict}" + else: + # print(f"UOM different {_poline['UOM']} <> {_dict['UOM']}") + Error_msg = f"UOM different {_poline['UOM']} <> {_dict['UOM']}" + else: + # print("errorpoline <>DN") + Error_msg = f"poline[ItemFullName] <> DN[FullName]; {_poline['ItemFullName']} <> {_dict['FullName']}, maybe there are 2 same namefromtaco in QB" + else: + pass + # print(f"this refnum {_dict['RefNum']} have no QB PO Return Line") + Error_msg = f"this refnum {_dict['RefNum']} have no QB PO Return Line" + + # print (_bol_dictisadded, Error_msg) + return _bol_dictisadded, Error_msg + + + def prepareInvoice(self, df:pd.DataFrame = None): + # print(df) + _bolAllDNareOk = True + _notindflist=[] + _yescounter = 0 + _nocounter = 0 + if df is not None: + _dflist = df.to_dict('records') + # print(_dflist) + + # else: + # _dflist = self.dfDN.to_dict('records') + # print(self.dfDN) + # print(f'_dflist:{_dflist}') + for idx, xdf in enumerate(_dflist): + _boladdDN, _Errormsg = self.addDNQtyToSalesOrderList(xdf) + # print(f'prepareInvoice->_Errormsg:{_Errormsg}') + if _boladdDN: + _dflist[idx]['ADDED']=True + elif _Errormsg: + _dflist[idx]['ERROR']=_Errormsg + for xdf in (_dflist): + if 'ADDED' not in xdf: + # print (f"prepareInvoice->not added: {xdf['Item No']}") + print (f"prepareInvoice->not added: {xdf}") + + _notindflist.append(xdf) + _nocounter+=1 + _bolAllDNareOk = False + else: + print (f"ADDED: {xdf['Item No']}") + + print(f'{len(_dflist) - _nocounter} of {len(_dflist)} are added') + return _bolAllDNareOk, _notindflist + + + def validate_date(self, date_text): + if date_text is None: + return None + try: + return datetime.datetime.strptime(date_text, '%Y-%m-%d').date() + except ValueError: + return None + # raise ValueError("Incorrect data format, should be YYYY-MM-DD") + + def get_ext_doc_no_list(self, dndict=None): + if dndict: + dnlist = dndict['lines'] + else: + 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]) + # print(df) + ext_doc_no=df['RefNum'].unique().tolist() + if len(ext_doc_no)>0: + return df, ext_doc_no + else: + return df, None + + def get_open_so(self, response_string=None): + if not response_string: + response_string = self.connect_to_quickbooks(self.create_QBXML()) + + QBXML = ET.fromstring(response_string) + _OpenSalesOrderlist = [] + SalesOrderRets = QBXML.findall('.//SalesOrderRet') + # print(f'SalesOrderRets count:{len(SalesOrderRets)}') + for SalesOrderRet in SalesOrderRets: + IsFullyInvoiced = SalesOrderRet.find('IsFullyInvoiced').text + IsManuallyClosed = SalesOrderRet.find('IsManuallyClosed').text + if IsFullyInvoiced=='false' and IsManuallyClosed=='false': + txndate = SalesOrderRet.find('TxnDate').text + totalamount = SalesOrderRet.find('TotalAmount').text + refnumber = SalesOrderRet.find('RefNumber').text + + _OpenSalesOrderlist.append([SalesOrderRet.find('TxnID').text, txndate, totalamount, refnumber, ]) + # _OpenSalesOrderlist.append(SalesOrderRet.find('TxnID').text) + # RefNumber = SalesOrderRet.find('RefNumber').text + # Memo = SalesOrderRet.find('Memo').text + # CustomerFullName = SalesOrderRet.find('CustomerRef/FullName').text + # TxnID = SalesOrderRet.find('TxnID').text + # TotalAmount = SalesOrderRet.find('TotalAmount').text + # IsFullyReceived = SalesOrderRet.find('IsFullyReceived').text + # IsManuallyClosed = SalesOrderRet.find('IsManuallyClosed').text + # print(_OpenSalesOrderlist) + return _OpenSalesOrderlist + + def create_open_sales_order_qbxml(self, txnid:list, IncludeLineItems=True): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + SalesOrderQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "SalesOrderQueryRq","\n " ) + if len(txnid)>0: + for x in txnid: + TxnID = self.create_sub_element(ET, SalesOrderQueryRq, "TxnID", x, 6 ) + else: + return None + if IncludeLineItems: + IncludeLineItems = self.create_sub_element(ET, SalesOrderQueryRq, "IncludeLineItems", 'true', 4) + # if len(self.IncludeRetElement)>0: + # for x in self.IncludeRetElement: + # IncludeRetElement = self.create_sub_element(ET, SalesOrderQueryRq, "IncludeRetElement", x, 4) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + print(f'create_open_sale_order_qbxml->qbxml_query: {qbxml_query}') + return qbxml_query + + + def get_open_sales_order(self, txnlist:list): + print(f'txnid: {txnlist}', type(txnlist)) + txnid = [] + for x in txnlist: + if isinstance(x, list): + txnid.append(x[0]) + else: + txnid.append(x) + break + # txnid = [x[0] if isinstance(x, list) else x for x in txnid ] + print(txnid) + if txnid: + # print(self.connect_to_quickbooks(self.create_open_sales_order_qbxml(txnid))) + return self._get_sales_order_header(self.connect_to_quickbooks(self.create_open_sales_order_qbxml(txnid))) + else: + print("There is No Open Sales Order") + return None + return None + +print('### SalesOrder ###') +if __name__ == '__main__': + starttime = timeit.default_timer() + # 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']) + # iya = ini.create_customerquery_QBXML() #pakai excel saja lebih cepat + # print(iya) + print(f'createQBXML:{ini.create_QBXML()}') + response_string = ini.connect_to_quickbooks(ini.create_QBXML()) + # print(f'response_string:{response_string}') + response_string = None + open_sales_orders = ini.get_open_so() + print(f'open sales orders:{open_sales_orders}') + if open_sales_orders: + + itu = ini.get_open_sales_order(open_sales_orders) + # print(itu) + print(f'get_open_sales_order:{itu}') + if itu: + + print(ini.create_invoiceadd_QBXML()) + + # ini.connect_to_quickbooks(ini.create_invoiceadd_QBXML()) + + print("The time difference is :", timeit.default_timer() - starttime) \ No newline at end of file diff --git a/SalesOrderQuery.xml b/SalesOrderQuery.xml new file mode 100644 index 0000000..5fa4b92 --- /dev/null +++ b/SalesOrderQuery.xml @@ -0,0 +1,336 @@ + + + + + + + IDTYPE + + STRTYPE + + STRTYPE + + INTTYPE + + + DATETIMETYPE + DATETIMETYPE + + + + + DATETYPE + DATETYPE + + + ENUMTYPE + + + + + + IDTYPE + + STRTYPE + + IDTYPE + + STRTYPE + + + + + + ENUMTYPE + STRTYPE + + + + STRTYPE + STRTYPE + + + + + IDTYPE + + STRTYPE + + + + BOOLTYPE + BOOLTYPE + STRTYPE + GUIDTYPE + + + + + IDTYPE + DATETIMETYPE + DATETIMETYPE + STRTYPE + INTTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + DATETYPE + STRTYPE + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + + STRTYPE + STRTYPE + STRTYPE + STRTYPE + STRTYPE + + STRTYPE + + IDTYPE + STRTYPE + + DATETYPE + + IDTYPE + STRTYPE + + STRTYPE + DATETYPE + + IDTYPE + STRTYPE + + AMTTYPE + + IDTYPE + STRTYPE + + PERCENTTYPE + AMTTYPE + AMTTYPE + + IDTYPE + STRTYPE + + FLOATTYPE + AMTTYPE + BOOLTYPE + BOOLTYPE + STRTYPE + + IDTYPE + STRTYPE + + BOOLTYPE + BOOLTYPE + BOOLTYPE + + IDTYPE + STRTYPE + + STRTYPE + GUIDTYPE + + IDTYPE + + ENUMTYPE + DATETYPE + STRTYPE + + ENUMTYPE + AMTTYPE + + + + IDTYPE + + IDTYPE + STRTYPE + + STRTYPE + QUANTYPE + STRTYPE + + IDTYPE + STRTYPE + + + PRICETYPE + + PERCENTTYPE + + + IDTYPE + STRTYPE + + AMTTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + STRTYPE + + STRTYPE + + STRTYPE + + IDTYPE + STRTYPE + + QUANTYPE + BOOLTYPE + STRTYPE + STRTYPE + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + + IDTYPE + + IDTYPE + STRTYPE + + STRTYPE + QUANTYPE + STRTYPE + + IDTYPE + STRTYPE + + BOOLTYPE + AMTTYPE + + IDTYPE + + IDTYPE + STRTYPE + + STRTYPE + QUANTYPE + STRTYPE + + IDTYPE + STRTYPE + + + PRICETYPE + + PERCENTTYPE + + + IDTYPE + STRTYPE + + AMTTYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + + STRTYPE + + STRTYPE + + STRTYPE + + IDTYPE + STRTYPE + + QUANTYPE + BOOLTYPE + STRTYPE + STRTYPE + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + + + + GUIDTYPE + STRTYPE + + ENUMTYPE + STRTYPE + + ENUMTYPE + + + IDTYPE + STRTYPE + STRTYPE + AMTTYPE + + + ENUMTYPE + STRTYPE + STRTYPE + + + + \ No newline at end of file diff --git a/TransactionQuery.xml b/TransactionQuery.xml new file mode 100644 index 0000000..e0f3479 --- /dev/null +++ b/TransactionQuery.xml @@ -0,0 +1,147 @@ + + + + + + + IDTYPE + + INTTYPE + + STRTYPE + + STRTYPE + + + + ENUMTYPE + STRTYPE + + + + STRTYPE + STRTYPE + + + + + DATETIMETYPE + DATETIMETYPE + + + ENUMTYPE + + + + + DATETYPE + DATETYPE + + + ENUMTYPE + + + + + + ENUMTYPE + + IDTYPE + + STRTYPE + + IDTYPE + + STRTYPE + + + + + + ENUMTYPE + + IDTYPE + + STRTYPE + + IDTYPE + + STRTYPE + + + + + + ENUMTYPE + + IDTYPE + + STRTYPE + + IDTYPE + + STRTYPE + + + + + IDTYPE + + STRTYPE + + IDTYPE + + STRTYPE + + + + + ENUMTYPE + + + ENUMTYPE + + ENUMTYPE + + ENUMTYPE + + + IDTYPE + + STRTYPE + + + + STRTYPE + + + + + + ENUMTYPE + IDTYPE + IDTYPE + DATETIMETYPE + DATETIMETYPE + + IDTYPE + STRTYPE + + + IDTYPE + STRTYPE + + DATETYPE + STRTYPE + AMTTYPE + + IDTYPE + STRTYPE + + FLOATTYPE + AMTTYPE + STRTYPE + + + + \ No newline at end of file diff --git a/database.db b/database.db new file mode 100644 index 0000000..0bcb3c6 Binary files /dev/null and b/database.db differ diff --git a/django/.gitignore b/django/.gitignore new file mode 100644 index 0000000..dbbdd78 --- /dev/null +++ b/django/.gitignore @@ -0,0 +1,166 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +#excel files +*.xlsx +*.xls + +ItemInventory/ \ No newline at end of file diff --git a/django/Customer/__init__.py b/django/Customer/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django/Customer/admin.py b/django/Customer/admin.py new file mode 100644 index 0000000..7e85ea0 --- /dev/null +++ b/django/Customer/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin +from .models import Customer + +admin.site.register(Customer) diff --git a/django/Customer/apps.py b/django/Customer/apps.py new file mode 100644 index 0000000..4951322 --- /dev/null +++ b/django/Customer/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class CustomerConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'Customer' diff --git a/django/Customer/forms.py b/django/Customer/forms.py new file mode 100644 index 0000000..2bd5c1f --- /dev/null +++ b/django/Customer/forms.py @@ -0,0 +1,7 @@ +from django.forms import ModelForm +from .models import Customer + +class CustomerForm(ModelForm): + class Meta: + model = Customer + fields = "__all__" \ No newline at end of file diff --git a/django/Customer/migrations/0001_initial.py b/django/Customer/migrations/0001_initial.py new file mode 100644 index 0000000..98f359c --- /dev/null +++ b/django/Customer/migrations/0001_initial.py @@ -0,0 +1,69 @@ +# Generated by Django 4.2 on 2023-05-02 10:31 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Customer', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('TimeCreated', models.DateTimeField(auto_created=True)), + ('CustomerName', models.CharField(max_length=80)), + ('CustomerFullName', models.CharField(max_length=160)), + ('CustomerIsActive', models.BooleanField(default=True)), + ('Sublevel', models.PositiveSmallIntegerField(default=0)), + ('CompanyName', models.CharField(max_length=80)), + ('Salutation', models.CharField(max_length=5)), + ('FirstName', models.CharField(max_length=80)), + ('MiddleName', models.CharField(blank=True, max_length=80, null=True)), + ('LastName', models.CharField(blank=True, max_length=80, null=True)), + ('BillAddr1', models.CharField(max_length=80)), + ('BillAddr2', models.CharField(blank=True, max_length=80, null=True)), + ('BillAddr3', models.CharField(blank=True, max_length=80, null=True)), + ('BillAddr4', models.CharField(blank=True, max_length=80, null=True)), + ('BillAddr5', models.CharField(blank=True, max_length=80, null=True)), + ('BillCity', models.CharField(blank=True, max_length=80, null=True)), + ('BillState', models.CharField(blank=True, max_length=80, null=True)), + ('BillPostalCode', models.CharField(blank=True, max_length=80, null=True)), + ('BillCountry', models.CharField(default='Indonesia', max_length=80)), + ('BillNote', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr1', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr2', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr3', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr4', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr5', models.CharField(blank=True, max_length=80, null=True)), + ('ShipCity', models.CharField(blank=True, max_length=80, null=True)), + ('ShipState', models.CharField(blank=True, max_length=80, null=True)), + ('ShipPostalCode', models.CharField(blank=True, max_length=80, null=True)), + ('ShipCountry', models.CharField(blank=True, max_length=80, null=True)), + ('ShipNote', models.CharField(blank=True, max_length=200, null=True)), + ('Phone', models.CharField(blank=True, max_length=80, null=True)), + ('Contact', models.CharField(max_length=80)), + ('Notes', models.CharField(blank=True, max_length=200, null=True)), + ('AltPhone', models.CharField(blank=True, max_length=25, null=True)), + ('Fax', models.CharField(blank=True, max_length=25, null=True)), + ('Email', models.CharField(blank=True, max_length=50, null=True)), + ('AltContact', models.CharField(blank=True, max_length=50, null=True)), + ('CreditLimit', models.DecimalField(blank=True, decimal_places=2, max_digits=12, null=True)), + ('NPWP', models.CharField(max_length=20)), + ('KTP', models.CharField(max_length=16)), + ('DMS_Cust_Name', models.CharField(max_length=80)), + ('DMS_Cust_Code', models.CharField(max_length=80)), + ('Special_Cust', models.BooleanField(default=False)), + ('EFaktur_Name', models.CharField(max_length=80)), + ('Efaktur_Address', models.CharField(max_length=80)), + ('Coordinates', models.CharField(blank=True, max_length=50, null=True)), + ('TimeModified', models.DateTimeField(auto_now=True)), + ('Parent', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='Customer.customer')), + ], + ), + ] diff --git a/django/Customer/migrations/0002_alter_customer_timecreated.py b/django/Customer/migrations/0002_alter_customer_timecreated.py new file mode 100644 index 0000000..770b031 --- /dev/null +++ b/django/Customer/migrations/0002_alter_customer_timecreated.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-05-02 10:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Customer', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='customer', + name='TimeCreated', + field=models.DateTimeField(auto_now_add=True), + ), + ] diff --git a/django/Customer/migrations/0003_alter_customer_parent.py b/django/Customer/migrations/0003_alter_customer_parent.py new file mode 100644 index 0000000..815663a --- /dev/null +++ b/django/Customer/migrations/0003_alter_customer_parent.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2 on 2023-05-02 10:51 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('Customer', '0002_alter_customer_timecreated'), + ] + + operations = [ + migrations.AlterField( + model_name='customer', + name='Parent', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='Customer.customer'), + ), + ] diff --git a/django/Customer/migrations/0004_customer_pricelevelreffullname.py b/django/Customer/migrations/0004_customer_pricelevelreffullname.py new file mode 100644 index 0000000..ca2a264 --- /dev/null +++ b/django/Customer/migrations/0004_customer_pricelevelreffullname.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2 on 2023-05-08 06:06 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('Item', '0008_alter_pricelevelitem_pl'), + ('Customer', '0003_alter_customer_parent'), + ] + + operations = [ + migrations.AddField( + model_name='customer', + name='PriceLevelRefFullName', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='PriceList', to='Item.pricelevel'), + ), + ] diff --git a/django/Customer/migrations/0005_alter_customer_coordinates_and_more.py b/django/Customer/migrations/0005_alter_customer_coordinates_and_more.py new file mode 100644 index 0000000..bbd6e20 --- /dev/null +++ b/django/Customer/migrations/0005_alter_customer_coordinates_and_more.py @@ -0,0 +1,48 @@ +# Generated by Django 4.2 on 2023-05-13 18:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Customer', '0004_customer_pricelevelreffullname'), + ] + + operations = [ + migrations.AlterField( + model_name='customer', + name='Coordinates', + field=models.CharField(blank=True, max_length=30, null=True), + ), + migrations.AlterField( + model_name='customer', + name='DMS_Cust_Code', + field=models.CharField(blank=True, max_length=80, null=True), + ), + migrations.AlterField( + model_name='customer', + name='DMS_Cust_Name', + field=models.CharField(blank=True, max_length=80, null=True), + ), + migrations.AlterField( + model_name='customer', + name='EFaktur_Name', + field=models.CharField(blank=True, max_length=80, null=True), + ), + migrations.AlterField( + model_name='customer', + name='Efaktur_Address', + field=models.CharField(blank=True, max_length=80, null=True), + ), + migrations.AlterField( + model_name='customer', + name='KTP', + field=models.CharField(blank=True, max_length=16, null=True), + ), + migrations.AlterField( + model_name='customer', + name='NPWP', + field=models.CharField(blank=True, max_length=20, null=True), + ), + ] diff --git a/django/Customer/migrations/0006_alter_customer_salutation.py b/django/Customer/migrations/0006_alter_customer_salutation.py new file mode 100644 index 0000000..103c708 --- /dev/null +++ b/django/Customer/migrations/0006_alter_customer_salutation.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-05-19 15:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Customer', '0005_alter_customer_coordinates_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='customer', + name='Salutation', + field=models.CharField(choices=[('Mr', 'Mr.'), ('Mrs', 'Mrs.')], max_length=4), + ), + ] diff --git a/django/Customer/migrations/0007_alter_customer_customerfullname.py b/django/Customer/migrations/0007_alter_customer_customerfullname.py new file mode 100644 index 0000000..738cb8a --- /dev/null +++ b/django/Customer/migrations/0007_alter_customer_customerfullname.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-08-31 10:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Customer', '0006_alter_customer_salutation'), + ] + + operations = [ + migrations.AlterField( + model_name='customer', + name='CustomerFullName', + field=models.CharField(max_length=160, unique=True), + ), + ] diff --git a/django/Customer/migrations/__init__.py b/django/Customer/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django/Customer/models.py b/django/Customer/models.py new file mode 100644 index 0000000..328d2ca --- /dev/null +++ b/django/Customer/models.py @@ -0,0 +1,97 @@ +from django.db import models +from django.urls import reverse +from Item.models import PriceLevel + +class Customer(models.Model): + MR = 'Mr' + MRS = 'Mrs' + + SALUTATION_CHOICE = [ + (MR, 'Mr.'), + (MRS, 'Mrs.'), + ] + + CustomerName = models.CharField(max_length=80) + CustomerFullName = models.CharField(max_length=160, unique=True) + CustomerIsActive = models.BooleanField(default=True) + Parent = models.ForeignKey("Customer", on_delete=models.DO_NOTHING, blank=True, null=True) + Sublevel = models.PositiveSmallIntegerField(default=0) + CompanyName = models.CharField(max_length=80) + Salutation = models.CharField(max_length=4, choices=SALUTATION_CHOICE) + FirstName = models.CharField(max_length=80) + MiddleName = models.CharField(max_length=80, blank=True, null=True) + LastName = models.CharField(max_length=80, blank=True, null=True) + BillAddr1 = models.CharField(max_length=80) + BillAddr2 = models.CharField(max_length=80, blank=True, null=True) + BillAddr3 = models.CharField(max_length=80, blank=True, null=True) + BillAddr4 = models.CharField(max_length=80, blank=True, null=True) + BillAddr5 = models.CharField(max_length=80, blank=True, null=True) + BillCity = models.CharField(max_length=80, blank=True, null=True) + BillState = models.CharField(max_length=80, blank=True, null=True) + BillPostalCode = models.CharField(max_length=80, blank=True, null=True) + BillCountry = models.CharField(max_length=80, default="Indonesia") + BillNote = models.CharField(max_length=80, blank=True, null=True) + ShipAddr1 = models.CharField(max_length=80, blank=True, null=True) + ShipAddr2 = models.CharField(max_length=80, blank=True, null=True) + ShipAddr3 = models.CharField(max_length=80, blank=True, null=True) + ShipAddr4 = models.CharField(max_length=80, blank=True, null=True) + ShipAddr5 = models.CharField(max_length=80, blank=True, null=True) + ShipCity = models.CharField(max_length=80, blank=True, null=True) + ShipState = models.CharField(max_length=80, blank=True, null=True) + ShipPostalCode = models.CharField(max_length=80, blank=True, null=True) + ShipCountry = models.CharField(max_length=80, blank=True, null=True) + ShipNote = models.CharField(max_length=200, blank=True, null=True) + Phone = models.CharField(max_length=80, blank=True, null=True) + Contact = models.CharField(max_length=80) + # CustomerTypeRefFullName + # TermsRefFullName + # SalesRepRefFullName + # Balance + # TotalBalance + # SalesTaxCodeRefFullName + # ItemSalesTaxRefFullName + # CreditCardNo + # ExpirationMonth + # ExpirationYear + # NameOnCard + # CreditCardAddress + # CreditCardPostalCode + # JobStatus + # JobStartDate + # JobProjectedEndDate + # JobEndDate + # JobTypeRefFullName + Notes = models.CharField(max_length=200, blank=True, null=True) + PriceLevelRefFullName = models.ForeignKey("Item.PriceLevel", related_name="PriceList", on_delete=models.SET_NULL, blank=True, null=True) + # CurrencyRefFullName + AltPhone = models.CharField(max_length=25, blank=True, null=True) + Fax = models.CharField(max_length=25, blank=True, null=True) + Email = models.CharField(max_length=50, blank=True, null=True) + AltContact = models.CharField(max_length=50, blank=True, null=True) + # ResaleNumber + # AccountNumber + CreditLimit = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True) + # PreferredPaymentMethodRefFullName + NPWP = models.CharField(max_length=20, blank=True, null=True) + KTP = models.CharField(max_length=16, blank=True, null=True) + DMS_Cust_Name = models.CharField(max_length=80, blank=True, null=True) + DMS_Cust_Code = models.CharField(max_length=80, blank=True, null=True) + Special_Cust = models.BooleanField(default=False) + EFaktur_Name = models.CharField(max_length=80, blank=True, null=True) + Efaktur_Address = models.CharField(max_length=80, blank=True, null=True) + Coordinates = models.CharField(max_length=30, blank=True, null=True) + TimeCreated = models.DateTimeField(auto_now_add=True) + TimeModified = models.DateTimeField(auto_now=True) + + def __str__(self): + return f"{self.CustomerName}; {self.PriceLevelRefFullName}" + + def get_field_name(obj): + # return [(f.name, f.value_to_string(obj)) for f in obj._meta.fields] #get value convert it to string + return [(f.verbose_name, f.name, f.value_from_object(obj)) for f in obj._meta.fields] + + def get_absolute_url(self): + return reverse('Customer:edit_customer', args=[str(self.id)]) + + + diff --git a/django/Customer/templates/Customer/addedit.html b/django/Customer/templates/Customer/addedit.html new file mode 100644 index 0000000..428a2af --- /dev/null +++ b/django/Customer/templates/Customer/addedit.html @@ -0,0 +1,12 @@ +{% extends 'base.html' %} +{% load crispy_forms_tags %} +{% block title %}{{title}}{% endblock title %} + +{% block body %} +
+ {% csrf_token %} + {{form|crispy}} + {% comment %} {{form.CustomerName|as_crispy_field}} {% endcomment %} + +
+{% endblock body %} \ No newline at end of file diff --git a/django/Customer/templates/Customer/index copy.html b/django/Customer/templates/Customer/index copy.html new file mode 100644 index 0000000..4c1233b --- /dev/null +++ b/django/Customer/templates/Customer/index copy.html @@ -0,0 +1,62 @@ +{% extends 'base.html' %} + +{% block title %}test obj{% endblock title %} + +{% block search_nav %} +{% endblock search_nav %} + +{% block body %} +{% comment %} {{objects}} {% endcomment %} +{{objects.count}} + + {% for obj in objects %} + {% comment %} {{obj.0}} {% endcomment %} + {% if obj.itempricelevel__Price %} + + {% else %} + + {% endif %} + {% endfor %} + +{% comment %} {% for obj in objects %} +{{obj}} +{% endfor %} {% endcomment %} +
+ + +
+ +
+ test +
+ + +{% endblock body %} diff --git a/django/Customer/templates/Customer/index.html b/django/Customer/templates/Customer/index.html new file mode 100644 index 0000000..4ba25fd --- /dev/null +++ b/django/Customer/templates/Customer/index.html @@ -0,0 +1 @@ +{% include 'Item/table_index.html' with title="Customer Page" %} \ No newline at end of file diff --git a/django/Customer/tests.py b/django/Customer/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/django/Customer/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/django/Customer/urls.py b/django/Customer/urls.py new file mode 100644 index 0000000..a99f0c3 --- /dev/null +++ b/django/Customer/urls.py @@ -0,0 +1,9 @@ +from django.urls import path, include +from .views import index, edit_customer, add_customer, delete_customer +app_name = "Customer" +urlpatterns = [ + path('', index, name="index" ), + path('edit/', edit_customer, name="edit_customer" ), + path('add/', add_customer, name="add_customer" ), + path('delete/', delete_customer, name="delete_customer" ), +] \ No newline at end of file diff --git a/django/Customer/views.py b/django/Customer/views.py new file mode 100644 index 0000000..f975cc0 --- /dev/null +++ b/django/Customer/views.py @@ -0,0 +1,77 @@ +from django.shortcuts import render, redirect, get_object_or_404 +from django.urls import reverse +from .models import Customer +from django.db.models import Q +from django.core.paginator import Paginator +# from Item.models import Item, PriceLevel, PriceLevelItem +from .forms import CustomerForm + +# def index(request): +# context={} +# qs1 = Item.objects.filter(itempricelevel__PL__Name='B2020',).prefetch_related("itempricelevel").values('FullName','SalesPrice', 'itempricelevel__Price') +# qs2 = Item.objects.exclude(itempricelevel__PL__Name='B2020').prefetch_related("itempricelevel").values( "FullName", "SalesPrice", "AlwaysNull") +# print(qs2) +# qs = qs1.union(qs2) +# print(type(qs)) +# print(qs) +# context['objects'] = qs +# return render(request, "Customer/index.html", context=context) + +def index(request): + context={} + search = request.GET.get("q") + customers=Customer.objects.all().order_by('CustomerFullName') + print(customers) + if search: + customer = Customer.objects.order_by('CustomerFullName').filter(Q(CustomerName__icontains=search) | Q(CustomerFullName__icontains=search)) + else: + customer = Customer.objects.order_by('CustomerFullName') + paginator = Paginator(customer, 25) # Show 25 contacts per page. + page_number = request.GET.get("page") + page_obj = paginator.get_page(page_number) + # heads = [f.name for f in Customer._meta.get_fields()] + # print(heads) + print(customer) + print(page_obj[0].CustomerName) + context['objects'] = page_obj + context['customers'] = customers + context['addurl'] = reverse('Customer:add_customer') + return render(request, "Customer/index.html", context=context) + +def edit_customer(request, pk): + print("edit customer") + print(pk) + print(request) + customer = get_object_or_404(Customer, pk=pk) + form = CustomerForm( request.POST or None, instance=customer) + if request.method == "GET": + print("GET") + if customer: + # form = CustomerForm(instance=customer) + return render(request, "Customer/addedit.html", {"objects": [customer,], "form":form}) + elif request.method == "POST": + print("POST") + # form = CustomerForm(request.POST, instance=customer) + if form.is_valid(): + print("form is valid") + customer=form.save() + # return redirect(reverse('Customer:edit_customer', kwargs={"pk":pk})) + return render(request, "Customer/index.html", {"objects": [customer]}) + else: + print("not valid form") + return render(request, "Customer/addedit.html", {"objects": [customer,], "form":form}) + +def add_customer(request): + print("add customer") + form = CustomerForm(request.POST or None) + if request.POST: + # print(form["CustomerName"].value()) + if form.is_valid(): + # print(form.cleaned_data["CustomerName"]) + form.save() + return redirect(reverse("Customer:index")) + # print(form["CustomerName"].value()) + return render(request, "Customer/addedit.html", {"form":form}) + +def delete_customer(request, pk): + print("delete customer") \ No newline at end of file diff --git a/django/Inventory/__init__.py b/django/Inventory/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django/Inventory/asgi.py b/django/Inventory/asgi.py new file mode 100644 index 0000000..be9503c --- /dev/null +++ b/django/Inventory/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for Inventory project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Inventory.settings') + +application = get_asgi_application() diff --git a/django/Inventory/settings.py b/django/Inventory/settings.py new file mode 100644 index 0000000..0692d89 --- /dev/null +++ b/django/Inventory/settings.py @@ -0,0 +1,143 @@ +""" +Django settings for Inventory project. + +Generated by 'django-admin startproject' using Django 4.2. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/4.2/ref/settings/ +""" + +from pathlib import Path +import os + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-u(al(30azswvgyf($b)cz-%h$8hl@o&i9glc9iv)!ikopl1!s-' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'debug_toolbar', + "crispy_forms", + "crispy_bootstrap5", + + "crispy_bootstrap4", + 'Item', + 'SalesOrder', + 'Invoice', + 'Customer', + 'django.contrib.humanize', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'debug_toolbar.middleware.DebugToolbarMiddleware', +] + +ROOT_URLCONF = 'Inventory.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [BASE_DIR / 'templates'], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'Inventory.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/4.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/4.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'Asia/Jakarta' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.2/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +INTERNAL_IPS = [ + '127.0.0.1', +] + +CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5" + +CRISPY_TEMPLATE_PACK = "bootstrap5" \ No newline at end of file diff --git a/django/Inventory/urls.py b/django/Inventory/urls.py new file mode 100644 index 0000000..ac30c0e --- /dev/null +++ b/django/Inventory/urls.py @@ -0,0 +1,33 @@ +""" +URL configuration for Inventory project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include +from django.conf import settings + +urlpatterns = [ + path('admin/', admin.site.urls), + # path('', include("SalesOrder.urls")), + path('customer/', include("Customer.urls")), + path('item/', include("Item.urls")), + path('so/', include("SalesOrder.urls")), + path('inv/', include("Invoice.urls")), + +] + +if settings.DEBUG: + import debug_toolbar + urlpatterns += path('__debug__/', include(debug_toolbar.urls)), \ No newline at end of file diff --git a/django/Inventory/wsgi.py b/django/Inventory/wsgi.py new file mode 100644 index 0000000..50d536a --- /dev/null +++ b/django/Inventory/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for Inventory project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Inventory.settings') + +application = get_wsgi_application() diff --git a/django/Invoice/__init__.py b/django/Invoice/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django/Invoice/admin.py b/django/Invoice/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/django/Invoice/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/django/Invoice/apps.py b/django/Invoice/apps.py new file mode 100644 index 0000000..60424e0 --- /dev/null +++ b/django/Invoice/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class InvoiceConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'Invoice' diff --git a/django/Invoice/forms.py b/django/Invoice/forms.py new file mode 100644 index 0000000..3bec721 --- /dev/null +++ b/django/Invoice/forms.py @@ -0,0 +1,54 @@ +from django.forms import ModelForm +from django import forms +from .models import Invoice, InvoiceItemLine +from crispy_forms.helper import FormHelper + +class InvoiceForm(ModelForm): + class Meta: + model = Invoice + fields = "__all__" + widgets = { + 'TxnDate' : forms.DateInput(attrs={'type':"date"}), + 'BillAddr1' : forms.Textarea(attrs={'rows':7, 'style':'height:180px'}), + 'ShipAddr1' : forms.Textarea(attrs={'rows':7, 'style':'height:180px'}), + 'TotalAmount' : forms.TextInput(attrs={'class':'text-end hidden', 'onkeypress':'return event.preventDefault()'}) + } + def __init__(self, *args, **kwargs): + super(InvoiceForm, self).__init__(*args, **kwargs) + self.helper = FormHelper(self) + # self.helper.form_show_labels = False + self.fields['TotalAmount'].label = False + self.fields['TotalAmount'].field_class = '' + +class InvoiceItemLineForm(ModelForm): + class Meta: + model = InvoiceItemLine + fields = ('ItemRefFullName', 'Desc', 'Quantity', 'UnitOfMeasure', 'Rate', 'Amount', 'Invoiced', 'LineIsManuallyClosed') + # fields = "__all__" + widgets = { + # 'ItemRefFullName' : forms.Select(choices=[('1', '1')]), + 'ItemRefFullName' : forms.NumberInput(attrs={'class':'hidden itemreffullname'}), + 'Desc' : forms.TextInput(attrs={'class':'desc'}), + 'Quantity' : forms.TextInput(attrs={'class':'quantity','onkeypress':'numberOnly(event)'}), #'onkeypress':'return (event.charCode >= 48 && event.charCode <= 57) || event.charCode == 46'}), + 'UnitOfMeasure' : forms.Select(attrs={'class':'unitofmeasure'}), + 'Rate' : forms.TextInput(attrs={'class':'rate text-end', 'onkeypress':'numberOnly(event)'}), + 'Amount' : forms.TextInput(attrs={'class':'amount text-end', 'onkeypress':'numberOnly(event)', 'onchange':'amountchanged(event)'}), + } + + def __init__(self, *args, **kwargs): + super(InvoiceItemLineForm, self).__init__(*args, **kwargs) + self.helper = FormHelper(self) + self.helper.form_show_labels = False + # self.helper.form_class = "abc" + # self.helper.field_class = "xyz" + + + +DEMO_CHOICES =( + ("1", "Naveen"), + ("2", "Pranav"), + ("3", "Isha"), + ("4", "Saloni"), +) +class GeeksForm(forms.Form): + geeks_field = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices = DEMO_CHOICES) \ No newline at end of file diff --git a/django/Invoice/migrations/0001_initial.py b/django/Invoice/migrations/0001_initial.py new file mode 100644 index 0000000..7500104 --- /dev/null +++ b/django/Invoice/migrations/0001_initial.py @@ -0,0 +1,83 @@ +# Generated by Django 4.2 on 2023-08-31 10:31 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('Customer', '0007_alter_customer_customerfullname'), + ('Item', '0010_alter_pricelevelitem_price'), + ] + + operations = [ + migrations.CreateModel( + name='Invoice', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('TxnDate', models.DateField()), + ('RefNumber', models.CharField(max_length=30, verbose_name='S.O. No.')), + ('BillAddr1', models.CharField(max_length=80, verbose_name='Name/Address')), + ('BillAddr2', models.CharField(blank=True, max_length=80, null=True)), + ('BillAddr3', models.CharField(blank=True, max_length=80, null=True)), + ('BillAddr4', models.CharField(blank=True, max_length=80, null=True)), + ('BillAddr5', models.CharField(blank=True, max_length=80, null=True)), + ('BillCity', models.CharField(blank=True, max_length=80, null=True)), + ('BillState', models.CharField(blank=True, max_length=80, null=True)), + ('BillPostalCode', models.CharField(blank=True, max_length=80, null=True)), + ('BillCountry', models.CharField(blank=True, default='Indonesia', max_length=80, null=True)), + ('BillNote', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr1', models.CharField(blank=True, max_length=80, null=True, verbose_name='Ship To')), + ('ShipAddr2', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr3', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr4', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr5', models.CharField(blank=True, max_length=80, null=True)), + ('ShipCity', models.CharField(blank=True, max_length=80, null=True)), + ('ShipState', models.CharField(blank=True, max_length=80, null=True)), + ('ShipPostalCode', models.CharField(blank=True, max_length=80, null=True)), + ('ShipCountry', models.CharField(blank=True, max_length=80, null=True)), + ('ShipNote', models.CharField(blank=True, max_length=200, null=True)), + ('PONumber', models.CharField(blank=True, max_length=30, null=True, verbose_name='PO. No.')), + ('TermsRefFullName', models.CharField(blank=True, max_length=10, null=True, verbose_name='Terms')), + ('SalesRepRefFullName', models.CharField(blank=True, max_length=10, null=True, verbose_name='REP')), + ('ShipDate', models.DateTimeField(blank=True, null=True)), + ('DueDate', models.DateField(blank=True, null=True)), + ('TotalAmount', models.DecimalField(blank=True, decimal_places=2, max_digits=14, null=True)), + ('CustomerMsgRefFullName', models.CharField(blank=True, max_length=120, null=True)), + ('IsToBePrinted', models.BooleanField(default=False)), + ('IsToBeEmailed', models.BooleanField(default=False)), + ('IsManuallyClosed', models.BooleanField(default=False)), + ('IsFullyInvoiced', models.BooleanField(default=False)), + ('Memo', models.CharField(blank=True, max_length=120, null=True)), + ('NPWP', models.CharField(blank=True, max_length=20, null=True)), + ('KTP', models.CharField(blank=True, max_length=16, null=True)), + ('DMS_Cust_Name', models.CharField(blank=True, max_length=80, null=True)), + ('DMS_Cust_Code', models.CharField(blank=True, max_length=80, null=True)), + ('Special_Cust', models.BooleanField(default=False)), + ('EFaktur_Name', models.CharField(blank=True, max_length=80, null=True)), + ('Efaktur_Address', models.CharField(blank=True, max_length=80, null=True)), + ('Coordinates', models.CharField(blank=True, max_length=30, null=True)), + ('TimeCreated', models.DateTimeField(auto_now_add=True)), + ('TimeModified', models.DateTimeField(auto_now=True)), + ('CustomerRefFullName', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='Customer.customer')), + ], + ), + migrations.CreateModel( + name='InvoiceItemLine', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('Desc', models.CharField(blank=True, max_length=80, null=True)), + ('Quantity', models.DecimalField(blank=True, decimal_places=2, max_digits=6, null=True)), + ('Rate', models.DecimalField(blank=True, decimal_places=2, max_digits=11, null=True)), + ('Amount', models.DecimalField(blank=True, decimal_places=2, max_digits=14, null=True)), + ('Invoiced', models.DecimalField(blank=True, decimal_places=2, max_digits=6, null=True)), + ('LineIsManuallyClosed', models.BooleanField(blank=True, default=False, null=True)), + ('Invoice', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='Invoice.invoice')), + ('ItemRefFullName', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='Item.item')), + ('UnitOfMeasure', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='Item.uom', verbose_name='UOM')), + ], + ), + ] diff --git a/django/Invoice/migrations/__init__.py b/django/Invoice/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django/Invoice/models.py b/django/Invoice/models.py new file mode 100644 index 0000000..c182cb8 --- /dev/null +++ b/django/Invoice/models.py @@ -0,0 +1,135 @@ +from django.db import models +from django.urls import reverse +from Item.models import Item, UOM +from Customer.models import Customer + +class Invoice(models.Model): + CustomerRefFullName = models.ForeignKey(Customer, on_delete=models.PROTECT) + # TxnNumber + # ClassRefFullName + # TemplateRefFullName + TxnDate = models.DateField() + RefNumber = models.CharField(max_length=30, verbose_name="S.O. No.") + BillAddr1 = models.CharField(max_length=80, verbose_name="Name/Address") + BillAddr2 = models.CharField(max_length=80, blank=True, null=True) + BillAddr3 = models.CharField(max_length=80, blank=True, null=True) + BillAddr4 = models.CharField(max_length=80, blank=True, null=True) + BillAddr5 = models.CharField(max_length=80, blank=True, null=True) + BillCity = models.CharField(max_length=80, blank=True, null=True) + BillState = models.CharField(max_length=80, blank=True, null=True) + BillPostalCode = models.CharField(max_length=80, blank=True, null=True) + BillCountry = models.CharField(max_length=80, default="Indonesia", blank=True, null=True) + BillNote = models.CharField(max_length=80, blank=True, null=True) + # Addr1 = + # Addr2 + # Addr3 + ShipAddr1 = models.CharField(max_length=80, verbose_name="Ship To", blank=True, null=True) + ShipAddr2 = models.CharField(max_length=80, blank=True, null=True) + ShipAddr3 = models.CharField(max_length=80, blank=True, null=True) + ShipAddr4 = models.CharField(max_length=80, blank=True, null=True) + ShipAddr5 = models.CharField(max_length=80, blank=True, null=True) + ShipCity = models.CharField(max_length=80, blank=True, null=True) + ShipState = models.CharField(max_length=80, blank=True, null=True) + ShipPostalCode = models.CharField(max_length=80, blank=True, null=True) + ShipCountry = models.CharField(max_length=80, blank=True, null=True) + ShipNote = models.CharField(max_length=200, blank=True, null=True) + + # ShipAddr1 + # ShipAddr2 + # ShipAddr3 + # ShipAddr4 + # ShipCity + # ShipState + # ShipPostalCode + # ShipCountry + # City + # State + # PostalCode + # Country_Note + PONumber = models.CharField(max_length=30, verbose_name="PO. No.", blank=True, null=True) + TermsRefFullName = models.CharField(max_length=10, verbose_name="Terms", blank=True, null=True) + SalesRepRefFullName = models.CharField(max_length=10, verbose_name="REP", blank=True, null=True) + ShipDate = models.DateTimeField(blank=True, null=True) + # ShipMethodRefFullName = + DueDate = models.DateField(blank=True, null=True) + # Subtotal = models.DecimalField(max_digits=14, decimal_places=2, blank=True, null=True) + + # ItemSalesTaxRefFullName + # SalesTaxPercentage + # SalesTaxTotal + # CurrencyRefFullName + TotalAmount = models.DecimalField(max_digits=14, decimal_places=2, blank=True, null=True ) + # ExchangeRate + # TotalAmountInHomeCurrency + CustomerMsgRefFullName = models.CharField(max_length=120, blank=True, null=True) + IsToBePrinted = models.BooleanField(default=False) + IsToBeEmailed = models.BooleanField(default=False) + # CustomerSalesTaxCodeRefFullName + # Other + # FOB + IsManuallyClosed = models.BooleanField(default=False) + IsFullyInvoiced = models.BooleanField(default=False) + Memo = models.CharField(max_length=120, blank=True, null=True) + # LinkedTxnID + # TxnLineID = models.ForeignKey(InvoiceItemLine, ondelete=models.DO_NOTHING) + + NPWP = models.CharField(max_length=20, blank=True, null=True) + KTP = models.CharField(max_length=16, blank=True, null=True) + DMS_Cust_Name = models.CharField(max_length=80, blank=True, null=True) + DMS_Cust_Code = models.CharField(max_length=80, blank=True, null=True) + Special_Cust = models.BooleanField(default=False) + EFaktur_Name = models.CharField(max_length=80, blank=True, null=True) + Efaktur_Address = models.CharField(max_length=80, blank=True, null=True) + Coordinates = models.CharField(max_length=30, blank=True, null=True) + TimeCreated = models.DateTimeField(auto_now_add=True) + TimeModified = models.DateTimeField(auto_now=True) + + def __str__(self): + return self.RefNumber + + def get_field_name(obj): + # return [(f.name, f.value_to_string(obj)) for f in obj._meta.fields] #get value convert it to string + return [(f.verbose_name, f.name, f.value_from_object(obj)) for f in obj._meta.fields] + + def get_absolute_url(self): + return reverse('Invoice:edit_so', args=[str(self.id)]) + + def save(self, *args, **kwargs): + + super().save(*args, **kwargs) + + +class InvoiceItemLine(models.Model): + Invoice = models.ForeignKey(Invoice, on_delete=models.PROTECT) + ItemRefFullName = models.ForeignKey(Item, on_delete=models.PROTECT) + Desc = models.CharField(max_length=80, blank=True, null=True) + Quantity = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True) + UnitOfMeasure = models.ForeignKey(UOM, verbose_name="UOM", on_delete=models.DO_NOTHING, blank=True, null=True) + # OverrideUOMFullName + Rate = models.DecimalField(max_digits=11, decimal_places=2, blank=True, null=True) + Amount = models.DecimalField(max_digits=14, decimal_places=2, blank=True, null=True) + # InventorySiteRefFullName + # SerialNumber + # LotNumber + # SalesTaxCodeRefFullName + # Other1 + # Other2 + Invoiced = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True) #how many qty that has invoiced + LineIsManuallyClosed = models.BooleanField(default=False, blank=True, null=True) + # LineClass + # GroupTxnLineID + # GroupItemFullName + # GroupDesc + # GroupQuantity + # IsPrintItemsInGroup + # RatePercent + # GroupLineTxnLineID + # GroupLineItemFullName + # GroupLineDesc + # GroupLineQuantity + # GroupLineUOM + # GroupLineOverrideUOM + # GroupLineRate + # GroupLineAmount + # GroupLineServiceDate + # GroupLineSalesTaxCodeFullName diff --git a/django/Invoice/static/bootstrap.bundle.min.js b/django/Invoice/static/bootstrap.bundle.min.js new file mode 100644 index 0000000..819659b --- /dev/null +++ b/django/Invoice/static/bootstrap.bundle.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v5.2.3 (https://getbootstrap.com/) + * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";const t="transitionend",e=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return e},i=t=>{const i=e(t);return i&&document.querySelector(i)?i:null},n=t=>{const i=e(t);return i?document.querySelector(i):null},s=e=>{e.dispatchEvent(new Event(t))},o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(t):null,a=t=>{if(!o(t)||0===t.getClientRects().length)return!1;const e="visible"===getComputedStyle(t).getPropertyValue("visibility"),i=t.closest("details:not([open])");if(!i)return e;if(i!==t){const e=t.closest("summary");if(e&&e.parentNode!==i)return!1;if(null===e)return!1}return e},l=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),c=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?c(t.parentNode):null},h=()=>{},d=t=>{t.offsetHeight},u=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,f=[],p=()=>"rtl"===document.documentElement.dir,g=t=>{var e;e=()=>{const e=u();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(f.length||document.addEventListener("DOMContentLoaded",(()=>{for(const t of f)t()})),f.push(e)):e()},m=t=>{"function"==typeof t&&t()},_=(e,i,n=!0)=>{if(!n)return void m(e);const o=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(i)+5;let r=!1;const a=({target:n})=>{n===i&&(r=!0,i.removeEventListener(t,a),m(e))};i.addEventListener(t,a),setTimeout((()=>{r||s(i)}),o)},b=(t,e,i,n)=>{const s=t.length;let o=t.indexOf(e);return-1===o?!i&&n?t[s-1]:t[0]:(o+=i?1:-1,n&&(o=(o+s)%s),t[Math.max(0,Math.min(o,s-1))])},v=/[^.]*(?=\..*)\.|.*/,y=/\..*/,w=/::\d+$/,A={};let E=1;const T={mouseenter:"mouseover",mouseleave:"mouseout"},C=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function O(t,e){return e&&`${e}::${E++}`||t.uidEvent||E++}function x(t){const e=O(t);return t.uidEvent=e,A[e]=A[e]||{},A[e]}function k(t,e,i=null){return Object.values(t).find((t=>t.callable===e&&t.delegationSelector===i))}function L(t,e,i){const n="string"==typeof e,s=n?i:e||i;let o=N(t);return C.has(o)||(o=t),[n,s,o]}function D(t,e,i,n,s){if("string"!=typeof e||!t)return;let[o,r,a]=L(e,i,n);if(e in T){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};r=t(r)}const l=x(t),c=l[a]||(l[a]={}),h=k(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=O(r,e.replace(v,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(const a of o)if(a===r)return j(s,{delegateTarget:r}),n.oneOff&&P.off(t,s.type,e,i),i.apply(r,[s])}}(t,i,r):function(t,e){return function i(n){return j(n,{delegateTarget:t}),i.oneOff&&P.off(t,n.type,e),e.apply(t,[n])}}(t,r);u.delegationSelector=o?i:null,u.callable=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function S(t,e,i,n,s){const o=k(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function I(t,e,i,n){const s=e[i]||{};for(const o of Object.keys(s))if(o.includes(n)){const n=s[o];S(t,e,i,n.callable,n.delegationSelector)}}function N(t){return t=t.replace(y,""),T[t]||t}const P={on(t,e,i,n){D(t,e,i,n,!1)},one(t,e,i,n){D(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=L(e,i,n),a=r!==e,l=x(t),c=l[r]||{},h=e.startsWith(".");if(void 0===o){if(h)for(const i of Object.keys(l))I(t,l,i,e.slice(1));for(const i of Object.keys(c)){const n=i.replace(w,"");if(!a||e.includes(n)){const e=c[i];S(t,l,r,e.callable,e.delegationSelector)}}}else{if(!Object.keys(c).length)return;S(t,l,r,o,s?i:null)}},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=u();let s=null,o=!0,r=!0,a=!1;e!==N(e)&&n&&(s=n.Event(e,i),n(t).trigger(s),o=!s.isPropagationStopped(),r=!s.isImmediatePropagationStopped(),a=s.isDefaultPrevented());let l=new Event(e,{bubbles:o,cancelable:!0});return l=j(l,i),a&&l.preventDefault(),r&&t.dispatchEvent(l),l.defaultPrevented&&s&&s.preventDefault(),l}};function j(t,e){for(const[i,n]of Object.entries(e||{}))try{t[i]=n}catch(e){Object.defineProperty(t,i,{configurable:!0,get:()=>n})}return t}const M=new Map,H={set(t,e,i){M.has(t)||M.set(t,new Map);const n=M.get(t);n.has(e)||0===n.size?n.set(e,i):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(n.keys())[0]}.`)},get:(t,e)=>M.has(t)&&M.get(t).get(e)||null,remove(t,e){if(!M.has(t))return;const i=M.get(t);i.delete(e),0===i.size&&M.delete(t)}};function $(t){if("true"===t)return!0;if("false"===t)return!1;if(t===Number(t).toString())return Number(t);if(""===t||"null"===t)return null;if("string"!=typeof t)return t;try{return JSON.parse(decodeURIComponent(t))}catch(e){return t}}function W(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}const B={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${W(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${W(e)}`)},getDataAttributes(t){if(!t)return{};const e={},i=Object.keys(t.dataset).filter((t=>t.startsWith("bs")&&!t.startsWith("bsConfig")));for(const n of i){let i=n.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1,i.length),e[i]=$(t.dataset[n])}return e},getDataAttribute:(t,e)=>$(t.getAttribute(`data-bs-${W(e)}`))};class F{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(t){return t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t}_mergeConfigObj(t,e){const i=o(e)?B.getDataAttribute(e,"config"):{};return{...this.constructor.Default,..."object"==typeof i?i:{},...o(e)?B.getDataAttributes(e):{},..."object"==typeof t?t:{}}}_typeCheckConfig(t,e=this.constructor.DefaultType){for(const n of Object.keys(e)){const s=e[n],r=t[n],a=o(r)?"element":null==(i=r)?`${i}`:Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(s).test(a))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${n}" provided type "${a}" but expected type "${s}".`)}var i}}class z extends F{constructor(t,e){super(),(t=r(t))&&(this._element=t,this._config=this._getConfig(e),H.set(this._element,this.constructor.DATA_KEY,this))}dispose(){H.remove(this._element,this.constructor.DATA_KEY),P.off(this._element,this.constructor.EVENT_KEY);for(const t of Object.getOwnPropertyNames(this))this[t]=null}_queueCallback(t,e,i=!0){_(t,e,i)}_getConfig(t){return t=this._mergeConfigObj(t,this._element),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}static getInstance(t){return H.get(r(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.2.3"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(t){return`${t}${this.EVENT_KEY}`}}const q=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,s=t.NAME;P.on(document,i,`[data-bs-dismiss="${s}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),l(this))return;const o=n(this)||this.closest(`.${s}`);t.getOrCreateInstance(o)[e]()}))};class R extends z{static get NAME(){return"alert"}close(){if(P.trigger(this._element,"close.bs.alert").defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),P.trigger(this._element,"closed.bs.alert"),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=R.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}q(R,"close"),g(R);const V='[data-bs-toggle="button"]';class K extends z{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=K.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}P.on(document,"click.bs.button.data-api",V,(t=>{t.preventDefault();const e=t.target.closest(V);K.getOrCreateInstance(e).toggle()})),g(K);const Q={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode.closest(e);for(;n;)i.push(n),n=n.parentNode.closest(e);return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(",");return this.find(e,t).filter((t=>!l(t)&&a(t)))}},X={endCallback:null,leftCallback:null,rightCallback:null},Y={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class U extends F{constructor(t,e){super(),this._element=t,t&&U.isSupported()&&(this._config=this._getConfig(e),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents())}static get Default(){return X}static get DefaultType(){return Y}static get NAME(){return"swipe"}dispose(){P.off(this._element,".bs.swipe")}_start(t){this._supportPointerEvents?this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX):this._deltaX=t.touches[0].clientX}_end(t){this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX-this._deltaX),this._handleSwipe(),m(this._config.endCallback)}_move(t){this._deltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this._deltaX}_handleSwipe(){const t=Math.abs(this._deltaX);if(t<=40)return;const e=t/this._deltaX;this._deltaX=0,e&&m(e>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(P.on(this._element,"pointerdown.bs.swipe",(t=>this._start(t))),P.on(this._element,"pointerup.bs.swipe",(t=>this._end(t))),this._element.classList.add("pointer-event")):(P.on(this._element,"touchstart.bs.swipe",(t=>this._start(t))),P.on(this._element,"touchmove.bs.swipe",(t=>this._move(t))),P.on(this._element,"touchend.bs.swipe",(t=>this._end(t))))}_eventIsPointerPenTouch(t){return this._supportPointerEvents&&("pen"===t.pointerType||"touch"===t.pointerType)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const G="next",J="prev",Z="left",tt="right",et="slid.bs.carousel",it="carousel",nt="active",st={ArrowLeft:tt,ArrowRight:Z},ot={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},rt={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class at extends z{constructor(t,e){super(t,e),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=Q.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===it&&this.cycle()}static get Default(){return ot}static get DefaultType(){return rt}static get NAME(){return"carousel"}next(){this._slide(G)}nextWhenVisible(){!document.hidden&&a(this._element)&&this.next()}prev(){this._slide(J)}pause(){this._isSliding&&s(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval((()=>this.nextWhenVisible()),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?P.one(this._element,et,(()=>this.cycle())):this.cycle())}to(t){const e=this._getItems();if(t>e.length-1||t<0)return;if(this._isSliding)return void P.one(this._element,et,(()=>this.to(t)));const i=this._getItemIndex(this._getActive());if(i===t)return;const n=t>i?G:J;this._slide(n,e[t])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(t){return t.defaultInterval=t.interval,t}_addEventListeners(){this._config.keyboard&&P.on(this._element,"keydown.bs.carousel",(t=>this._keydown(t))),"hover"===this._config.pause&&(P.on(this._element,"mouseenter.bs.carousel",(()=>this.pause())),P.on(this._element,"mouseleave.bs.carousel",(()=>this._maybeEnableCycle()))),this._config.touch&&U.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const t of Q.find(".carousel-item img",this._element))P.on(t,"dragstart.bs.carousel",(t=>t.preventDefault()));const t={leftCallback:()=>this._slide(this._directionToOrder(Z)),rightCallback:()=>this._slide(this._directionToOrder(tt)),endCallback:()=>{"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((()=>this._maybeEnableCycle()),500+this._config.interval))}};this._swipeHelper=new U(this._element,t)}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=st[t.key];e&&(t.preventDefault(),this._slide(this._directionToOrder(e)))}_getItemIndex(t){return this._getItems().indexOf(t)}_setActiveIndicatorElement(t){if(!this._indicatorsElement)return;const e=Q.findOne(".active",this._indicatorsElement);e.classList.remove(nt),e.removeAttribute("aria-current");const i=Q.findOne(`[data-bs-slide-to="${t}"]`,this._indicatorsElement);i&&(i.classList.add(nt),i.setAttribute("aria-current","true"))}_updateInterval(){const t=this._activeElement||this._getActive();if(!t)return;const e=Number.parseInt(t.getAttribute("data-bs-interval"),10);this._config.interval=e||this._config.defaultInterval}_slide(t,e=null){if(this._isSliding)return;const i=this._getActive(),n=t===G,s=e||b(this._getItems(),i,n,this._config.wrap);if(s===i)return;const o=this._getItemIndex(s),r=e=>P.trigger(this._element,e,{relatedTarget:s,direction:this._orderToDirection(t),from:this._getItemIndex(i),to:o});if(r("slide.bs.carousel").defaultPrevented)return;if(!i||!s)return;const a=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(o),this._activeElement=s;const l=n?"carousel-item-start":"carousel-item-end",c=n?"carousel-item-next":"carousel-item-prev";s.classList.add(c),d(s),i.classList.add(l),s.classList.add(l),this._queueCallback((()=>{s.classList.remove(l,c),s.classList.add(nt),i.classList.remove(nt,c,l),this._isSliding=!1,r(et)}),i,this._isAnimated()),a&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return Q.findOne(".active.carousel-item",this._element)}_getItems(){return Q.find(".carousel-item",this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(t){return p()?t===Z?J:G:t===Z?G:J}_orderToDirection(t){return p()?t===J?Z:tt:t===J?tt:Z}static jQueryInterface(t){return this.each((function(){const e=at.getOrCreateInstance(this,t);if("number"!=typeof t){if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}else e.to(t)}))}}P.on(document,"click.bs.carousel.data-api","[data-bs-slide], [data-bs-slide-to]",(function(t){const e=n(this);if(!e||!e.classList.contains(it))return;t.preventDefault();const i=at.getOrCreateInstance(e),s=this.getAttribute("data-bs-slide-to");return s?(i.to(s),void i._maybeEnableCycle()):"next"===B.getDataAttribute(this,"slide")?(i.next(),void i._maybeEnableCycle()):(i.prev(),void i._maybeEnableCycle())})),P.on(window,"load.bs.carousel.data-api",(()=>{const t=Q.find('[data-bs-ride="carousel"]');for(const e of t)at.getOrCreateInstance(e)})),g(at);const lt="show",ct="collapse",ht="collapsing",dt='[data-bs-toggle="collapse"]',ut={parent:null,toggle:!0},ft={parent:"(null|element)",toggle:"boolean"};class pt extends z{constructor(t,e){super(t,e),this._isTransitioning=!1,this._triggerArray=[];const n=Q.find(dt);for(const t of n){const e=i(t),n=Q.find(e).filter((t=>t===this._element));null!==e&&n.length&&this._triggerArray.push(t)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return ut}static get DefaultType(){return ft}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t=[];if(this._config.parent&&(t=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((t=>t!==this._element)).map((t=>pt.getOrCreateInstance(t,{toggle:!1})))),t.length&&t[0]._isTransitioning)return;if(P.trigger(this._element,"show.bs.collapse").defaultPrevented)return;for(const e of t)e.hide();const e=this._getDimension();this._element.classList.remove(ct),this._element.classList.add(ht),this._element.style[e]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const i=`scroll${e[0].toUpperCase()+e.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(ht),this._element.classList.add(ct,lt),this._element.style[e]="",P.trigger(this._element,"shown.bs.collapse")}),this._element,!0),this._element.style[e]=`${this._element[i]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(P.trigger(this._element,"hide.bs.collapse").defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,d(this._element),this._element.classList.add(ht),this._element.classList.remove(ct,lt);for(const t of this._triggerArray){const e=n(t);e&&!this._isShown(e)&&this._addAriaAndCollapsedClass([t],!1)}this._isTransitioning=!0,this._element.style[t]="",this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(ht),this._element.classList.add(ct),P.trigger(this._element,"hidden.bs.collapse")}),this._element,!0)}_isShown(t=this._element){return t.classList.contains(lt)}_configAfterMerge(t){return t.toggle=Boolean(t.toggle),t.parent=r(t.parent),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=this._getFirstLevelChildren(dt);for(const e of t){const t=n(e);t&&this._addAriaAndCollapsedClass([e],this._isShown(t))}}_getFirstLevelChildren(t){const e=Q.find(":scope .collapse .collapse",this._config.parent);return Q.find(t,this._config.parent).filter((t=>!e.includes(t)))}_addAriaAndCollapsedClass(t,e){if(t.length)for(const i of t)i.classList.toggle("collapsed",!e),i.setAttribute("aria-expanded",e)}static jQueryInterface(t){const e={};return"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1),this.each((function(){const i=pt.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}P.on(document,"click.bs.collapse.data-api",dt,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();const e=i(this),n=Q.find(e);for(const t of n)pt.getOrCreateInstance(t,{toggle:!1}).toggle()})),g(pt);var gt="top",mt="bottom",_t="right",bt="left",vt="auto",yt=[gt,mt,_t,bt],wt="start",At="end",Et="clippingParents",Tt="viewport",Ct="popper",Ot="reference",xt=yt.reduce((function(t,e){return t.concat([e+"-"+wt,e+"-"+At])}),[]),kt=[].concat(yt,[vt]).reduce((function(t,e){return t.concat([e,e+"-"+wt,e+"-"+At])}),[]),Lt="beforeRead",Dt="read",St="afterRead",It="beforeMain",Nt="main",Pt="afterMain",jt="beforeWrite",Mt="write",Ht="afterWrite",$t=[Lt,Dt,St,It,Nt,Pt,jt,Mt,Ht];function Wt(t){return t?(t.nodeName||"").toLowerCase():null}function Bt(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function Ft(t){return t instanceof Bt(t).Element||t instanceof Element}function zt(t){return t instanceof Bt(t).HTMLElement||t instanceof HTMLElement}function qt(t){return"undefined"!=typeof ShadowRoot&&(t instanceof Bt(t).ShadowRoot||t instanceof ShadowRoot)}const Rt={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];zt(s)&&Wt(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});zt(n)&&Wt(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}},requires:["computeStyles"]};function Vt(t){return t.split("-")[0]}var Kt=Math.max,Qt=Math.min,Xt=Math.round;function Yt(){var t=navigator.userAgentData;return null!=t&&t.brands?t.brands.map((function(t){return t.brand+"/"+t.version})).join(" "):navigator.userAgent}function Ut(){return!/^((?!chrome|android).)*safari/i.test(Yt())}function Gt(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1);var n=t.getBoundingClientRect(),s=1,o=1;e&&zt(t)&&(s=t.offsetWidth>0&&Xt(n.width)/t.offsetWidth||1,o=t.offsetHeight>0&&Xt(n.height)/t.offsetHeight||1);var r=(Ft(t)?Bt(t):window).visualViewport,a=!Ut()&&i,l=(n.left+(a&&r?r.offsetLeft:0))/s,c=(n.top+(a&&r?r.offsetTop:0))/o,h=n.width/s,d=n.height/o;return{width:h,height:d,top:c,right:l+h,bottom:c+d,left:l,x:l,y:c}}function Jt(t){var e=Gt(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function Zt(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&qt(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function te(t){return Bt(t).getComputedStyle(t)}function ee(t){return["table","td","th"].indexOf(Wt(t))>=0}function ie(t){return((Ft(t)?t.ownerDocument:t.document)||window.document).documentElement}function ne(t){return"html"===Wt(t)?t:t.assignedSlot||t.parentNode||(qt(t)?t.host:null)||ie(t)}function se(t){return zt(t)&&"fixed"!==te(t).position?t.offsetParent:null}function oe(t){for(var e=Bt(t),i=se(t);i&&ee(i)&&"static"===te(i).position;)i=se(i);return i&&("html"===Wt(i)||"body"===Wt(i)&&"static"===te(i).position)?e:i||function(t){var e=/firefox/i.test(Yt());if(/Trident/i.test(Yt())&&zt(t)&&"fixed"===te(t).position)return null;var i=ne(t);for(qt(i)&&(i=i.host);zt(i)&&["html","body"].indexOf(Wt(i))<0;){var n=te(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function re(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function ae(t,e,i){return Kt(t,Qt(e,i))}function le(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function ce(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}const he={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=Vt(i.placement),l=re(a),c=[bt,_t].indexOf(a)>=0?"height":"width";if(o&&r){var h=function(t,e){return le("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:ce(t,yt))}(s.padding,i),d=Jt(o),u="y"===l?gt:bt,f="y"===l?mt:_t,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],g=r[l]-i.rects.reference[l],m=oe(o),_=m?"y"===l?m.clientHeight||0:m.clientWidth||0:0,b=p/2-g/2,v=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+b,A=ae(v,w,y),E=l;i.modifiersData[n]=((e={})[E]=A,e.centerOffset=A-w,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&Zt(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function de(t){return t.split("-")[1]}var ue={top:"auto",right:"auto",bottom:"auto",left:"auto"};function fe(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=t.isFixed,u=r.x,f=void 0===u?0:u,p=r.y,g=void 0===p?0:p,m="function"==typeof h?h({x:f,y:g}):{x:f,y:g};f=m.x,g=m.y;var _=r.hasOwnProperty("x"),b=r.hasOwnProperty("y"),v=bt,y=gt,w=window;if(c){var A=oe(i),E="clientHeight",T="clientWidth";A===Bt(i)&&"static"!==te(A=ie(i)).position&&"absolute"===a&&(E="scrollHeight",T="scrollWidth"),(s===gt||(s===bt||s===_t)&&o===At)&&(y=mt,g-=(d&&A===w&&w.visualViewport?w.visualViewport.height:A[E])-n.height,g*=l?1:-1),s!==bt&&(s!==gt&&s!==mt||o!==At)||(v=_t,f-=(d&&A===w&&w.visualViewport?w.visualViewport.width:A[T])-n.width,f*=l?1:-1)}var C,O=Object.assign({position:a},c&&ue),x=!0===h?function(t){var e=t.x,i=t.y,n=window.devicePixelRatio||1;return{x:Xt(e*n)/n||0,y:Xt(i*n)/n||0}}({x:f,y:g}):{x:f,y:g};return f=x.x,g=x.y,l?Object.assign({},O,((C={})[y]=b?"0":"",C[v]=_?"0":"",C.transform=(w.devicePixelRatio||1)<=1?"translate("+f+"px, "+g+"px)":"translate3d("+f+"px, "+g+"px, 0)",C)):Object.assign({},O,((e={})[y]=b?g+"px":"",e[v]=_?f+"px":"",e.transform="",e))}const pe={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:Vt(e.placement),variation:de(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s,isFixed:"fixed"===e.options.strategy};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,fe(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,fe(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var ge={passive:!0};const me={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=Bt(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,ge)})),a&&l.addEventListener("resize",i.update,ge),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,ge)})),a&&l.removeEventListener("resize",i.update,ge)}},data:{}};var _e={left:"right",right:"left",bottom:"top",top:"bottom"};function be(t){return t.replace(/left|right|bottom|top/g,(function(t){return _e[t]}))}var ve={start:"end",end:"start"};function ye(t){return t.replace(/start|end/g,(function(t){return ve[t]}))}function we(t){var e=Bt(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function Ae(t){return Gt(ie(t)).left+we(t).scrollLeft}function Ee(t){var e=te(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function Te(t){return["html","body","#document"].indexOf(Wt(t))>=0?t.ownerDocument.body:zt(t)&&Ee(t)?t:Te(ne(t))}function Ce(t,e){var i;void 0===e&&(e=[]);var n=Te(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=Bt(n),r=s?[o].concat(o.visualViewport||[],Ee(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(Ce(ne(r)))}function Oe(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function xe(t,e,i){return e===Tt?Oe(function(t,e){var i=Bt(t),n=ie(t),s=i.visualViewport,o=n.clientWidth,r=n.clientHeight,a=0,l=0;if(s){o=s.width,r=s.height;var c=Ut();(c||!c&&"fixed"===e)&&(a=s.offsetLeft,l=s.offsetTop)}return{width:o,height:r,x:a+Ae(t),y:l}}(t,i)):Ft(e)?function(t,e){var i=Gt(t,!1,"fixed"===e);return i.top=i.top+t.clientTop,i.left=i.left+t.clientLeft,i.bottom=i.top+t.clientHeight,i.right=i.left+t.clientWidth,i.width=t.clientWidth,i.height=t.clientHeight,i.x=i.left,i.y=i.top,i}(e,i):Oe(function(t){var e,i=ie(t),n=we(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=Kt(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=Kt(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+Ae(t),l=-n.scrollTop;return"rtl"===te(s||i).direction&&(a+=Kt(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(ie(t)))}function ke(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?Vt(s):null,r=s?de(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;switch(o){case gt:e={x:a,y:i.y-n.height};break;case mt:e={x:a,y:i.y+i.height};break;case _t:e={x:i.x+i.width,y:l};break;case bt:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?re(o):null;if(null!=c){var h="y"===c?"height":"width";switch(r){case wt:e[c]=e[c]-(i[h]/2-n[h]/2);break;case At:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function Le(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.strategy,r=void 0===o?t.strategy:o,a=i.boundary,l=void 0===a?Et:a,c=i.rootBoundary,h=void 0===c?Tt:c,d=i.elementContext,u=void 0===d?Ct:d,f=i.altBoundary,p=void 0!==f&&f,g=i.padding,m=void 0===g?0:g,_=le("number"!=typeof m?m:ce(m,yt)),b=u===Ct?Ot:Ct,v=t.rects.popper,y=t.elements[p?b:u],w=function(t,e,i,n){var s="clippingParents"===e?function(t){var e=Ce(ne(t)),i=["absolute","fixed"].indexOf(te(t).position)>=0&&zt(t)?oe(t):t;return Ft(i)?e.filter((function(t){return Ft(t)&&Zt(t,i)&&"body"!==Wt(t)})):[]}(t):[].concat(e),o=[].concat(s,[i]),r=o[0],a=o.reduce((function(e,i){var s=xe(t,i,n);return e.top=Kt(s.top,e.top),e.right=Qt(s.right,e.right),e.bottom=Qt(s.bottom,e.bottom),e.left=Kt(s.left,e.left),e}),xe(t,r,n));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}(Ft(y)?y:y.contextElement||ie(t.elements.popper),l,h,r),A=Gt(t.elements.reference),E=ke({reference:A,element:v,strategy:"absolute",placement:s}),T=Oe(Object.assign({},v,E)),C=u===Ct?T:A,O={top:w.top-C.top+_.top,bottom:C.bottom-w.bottom+_.bottom,left:w.left-C.left+_.left,right:C.right-w.right+_.right},x=t.modifiersData.offset;if(u===Ct&&x){var k=x[s];Object.keys(O).forEach((function(t){var e=[_t,mt].indexOf(t)>=0?1:-1,i=[gt,mt].indexOf(t)>=0?"y":"x";O[t]+=k[i]*e}))}return O}function De(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?kt:l,h=de(n),d=h?a?xt:xt.filter((function(t){return de(t)===h})):yt,u=d.filter((function(t){return c.indexOf(t)>=0}));0===u.length&&(u=d);var f=u.reduce((function(e,i){return e[i]=Le(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[Vt(i)],e}),{});return Object.keys(f).sort((function(t,e){return f[t]-f[e]}))}const Se={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,g=i.allowedAutoPlacements,m=e.options.placement,_=Vt(m),b=l||(_!==m&&p?function(t){if(Vt(t)===vt)return[];var e=be(t);return[ye(t),e,ye(e)]}(m):[be(m)]),v=[m].concat(b).reduce((function(t,i){return t.concat(Vt(i)===vt?De(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:g}):i)}),[]),y=e.rects.reference,w=e.rects.popper,A=new Map,E=!0,T=v[0],C=0;C=0,D=L?"width":"height",S=Le(e,{placement:O,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),I=L?k?_t:bt:k?mt:gt;y[D]>w[D]&&(I=be(I));var N=be(I),P=[];if(o&&P.push(S[x]<=0),a&&P.push(S[I]<=0,S[N]<=0),P.every((function(t){return t}))){T=O,E=!1;break}A.set(O,P)}if(E)for(var j=function(t){var e=v.find((function(e){var i=A.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return T=e,"break"},M=p?3:1;M>0&&"break"!==j(M);M--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function Ie(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function Ne(t){return[gt,_t,mt,bt].some((function(e){return t[e]>=0}))}const Pe={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=Le(e,{elementContext:"reference"}),a=Le(e,{altBoundary:!0}),l=Ie(r,n),c=Ie(a,s,o),h=Ne(l),d=Ne(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},je={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=kt.reduce((function(t,i){return t[i]=function(t,e,i){var n=Vt(t),s=[bt,gt].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[bt,_t].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t}),{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}},Me={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=ke({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},He={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,g=void 0===p?0:p,m=Le(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=Vt(e.placement),b=de(e.placement),v=!b,y=re(_),w="x"===y?"y":"x",A=e.modifiersData.popperOffsets,E=e.rects.reference,T=e.rects.popper,C="function"==typeof g?g(Object.assign({},e.rects,{placement:e.placement})):g,O="number"==typeof C?{mainAxis:C,altAxis:C}:Object.assign({mainAxis:0,altAxis:0},C),x=e.modifiersData.offset?e.modifiersData.offset[e.placement]:null,k={x:0,y:0};if(A){if(o){var L,D="y"===y?gt:bt,S="y"===y?mt:_t,I="y"===y?"height":"width",N=A[y],P=N+m[D],j=N-m[S],M=f?-T[I]/2:0,H=b===wt?E[I]:T[I],$=b===wt?-T[I]:-E[I],W=e.elements.arrow,B=f&&W?Jt(W):{width:0,height:0},F=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},z=F[D],q=F[S],R=ae(0,E[I],B[I]),V=v?E[I]/2-M-R-z-O.mainAxis:H-R-z-O.mainAxis,K=v?-E[I]/2+M+R+q+O.mainAxis:$+R+q+O.mainAxis,Q=e.elements.arrow&&oe(e.elements.arrow),X=Q?"y"===y?Q.clientTop||0:Q.clientLeft||0:0,Y=null!=(L=null==x?void 0:x[y])?L:0,U=N+K-Y,G=ae(f?Qt(P,N+V-Y-X):P,N,f?Kt(j,U):j);A[y]=G,k[y]=G-N}if(a){var J,Z="x"===y?gt:bt,tt="x"===y?mt:_t,et=A[w],it="y"===w?"height":"width",nt=et+m[Z],st=et-m[tt],ot=-1!==[gt,bt].indexOf(_),rt=null!=(J=null==x?void 0:x[w])?J:0,at=ot?nt:et-E[it]-T[it]-rt+O.altAxis,lt=ot?et+E[it]+T[it]-rt-O.altAxis:st,ct=f&&ot?function(t,e,i){var n=ae(t,e,i);return n>i?i:n}(at,et,lt):ae(f?at:nt,et,f?lt:st);A[w]=ct,k[w]=ct-et}e.modifiersData[n]=k}},requiresIfExists:["offset"]};function $e(t,e,i){void 0===i&&(i=!1);var n,s,o=zt(e),r=zt(e)&&function(t){var e=t.getBoundingClientRect(),i=Xt(e.width)/t.offsetWidth||1,n=Xt(e.height)/t.offsetHeight||1;return 1!==i||1!==n}(e),a=ie(e),l=Gt(t,r,i),c={scrollLeft:0,scrollTop:0},h={x:0,y:0};return(o||!o&&!i)&&(("body"!==Wt(e)||Ee(a))&&(c=(n=e)!==Bt(n)&&zt(n)?{scrollLeft:(s=n).scrollLeft,scrollTop:s.scrollTop}:we(n)),zt(e)?((h=Gt(e,!0)).x+=e.clientLeft,h.y+=e.clientTop):a&&(h.x=Ae(a))),{x:l.left+c.scrollLeft-h.x,y:l.top+c.scrollTop-h.y,width:l.width,height:l.height}}function We(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}var Be={placement:"bottom",modifiers:[],strategy:"absolute"};function Fe(){for(var t=arguments.length,e=new Array(t),i=0;iNumber.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||"static"===this._config.display)&&(B.setDataAttribute(this._menu,"popper","static"),t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,..."function"==typeof this._config.popperConfig?this._config.popperConfig(t):this._config.popperConfig}}_selectMenuItem({key:t,target:e}){const i=Q.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter((t=>a(t)));i.length&&b(i,e,t===Ye,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=hi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(2===t.button||"keyup"===t.type&&"Tab"!==t.key)return;const e=Q.find(ti);for(const i of e){const e=hi.getInstance(i);if(!e||!1===e._config.autoClose)continue;const n=t.composedPath(),s=n.includes(e._menu);if(n.includes(e._element)||"inside"===e._config.autoClose&&!s||"outside"===e._config.autoClose&&s)continue;if(e._menu.contains(t.target)&&("keyup"===t.type&&"Tab"===t.key||/input|select|option|textarea|form/i.test(t.target.tagName)))continue;const o={relatedTarget:e._element};"click"===t.type&&(o.clickEvent=t),e._completeHide(o)}}static dataApiKeydownHandler(t){const e=/input|textarea/i.test(t.target.tagName),i="Escape"===t.key,n=[Xe,Ye].includes(t.key);if(!n&&!i)return;if(e&&!i)return;t.preventDefault();const s=this.matches(Ze)?this:Q.prev(this,Ze)[0]||Q.next(this,Ze)[0]||Q.findOne(Ze,t.delegateTarget.parentNode),o=hi.getOrCreateInstance(s);if(n)return t.stopPropagation(),o.show(),void o._selectMenuItem(t);o._isShown()&&(t.stopPropagation(),o.hide(),s.focus())}}P.on(document,Ge,Ze,hi.dataApiKeydownHandler),P.on(document,Ge,ei,hi.dataApiKeydownHandler),P.on(document,Ue,hi.clearMenus),P.on(document,"keyup.bs.dropdown.data-api",hi.clearMenus),P.on(document,Ue,Ze,(function(t){t.preventDefault(),hi.getOrCreateInstance(this).toggle()})),g(hi);const di=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",ui=".sticky-top",fi="padding-right",pi="margin-right";class gi{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,fi,(e=>e+t)),this._setElementAttributes(di,fi,(e=>e+t)),this._setElementAttributes(ui,pi,(e=>e-t))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,fi),this._resetElementAttributes(di,fi),this._resetElementAttributes(ui,pi)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t).getPropertyValue(e);t.style.setProperty(e,`${i(Number.parseFloat(s))}px`)}))}_saveInitialAttribute(t,e){const i=t.style.getPropertyValue(e);i&&B.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=B.getDataAttribute(t,e);null!==i?(B.removeDataAttribute(t,e),t.style.setProperty(e,i)):t.style.removeProperty(e)}))}_applyManipulationCallback(t,e){if(o(t))e(t);else for(const i of Q.find(t,this._element))e(i)}}const mi="show",_i="mousedown.bs.backdrop",bi={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},vi={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class yi extends F{constructor(t){super(),this._config=this._getConfig(t),this._isAppended=!1,this._element=null}static get Default(){return bi}static get DefaultType(){return vi}static get NAME(){return"backdrop"}show(t){if(!this._config.isVisible)return void m(t);this._append();const e=this._getElement();this._config.isAnimated&&d(e),e.classList.add(mi),this._emulateAnimation((()=>{m(t)}))}hide(t){this._config.isVisible?(this._getElement().classList.remove(mi),this._emulateAnimation((()=>{this.dispose(),m(t)}))):m(t)}dispose(){this._isAppended&&(P.off(this._element,_i),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_configAfterMerge(t){return t.rootElement=r(t.rootElement),t}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),P.on(t,_i,(()=>{m(this._config.clickCallback)})),this._isAppended=!0}_emulateAnimation(t){_(t,this._getElement(),this._config.isAnimated)}}const wi=".bs.focustrap",Ai="backward",Ei={autofocus:!0,trapElement:null},Ti={autofocus:"boolean",trapElement:"element"};class Ci extends F{constructor(t){super(),this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return Ei}static get DefaultType(){return Ti}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),P.off(document,wi),P.on(document,"focusin.bs.focustrap",(t=>this._handleFocusin(t))),P.on(document,"keydown.tab.bs.focustrap",(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,P.off(document,wi))}_handleFocusin(t){const{trapElement:e}=this._config;if(t.target===document||t.target===e||e.contains(t.target))return;const i=Q.focusableChildren(e);0===i.length?e.focus():this._lastTabNavDirection===Ai?i[i.length-1].focus():i[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?Ai:"forward")}}const Oi="hidden.bs.modal",xi="show.bs.modal",ki="modal-open",Li="show",Di="modal-static",Si={backdrop:!0,focus:!0,keyboard:!0},Ii={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class Ni extends z{constructor(t,e){super(t,e),this._dialog=Q.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new gi,this._addEventListeners()}static get Default(){return Si}static get DefaultType(){return Ii}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||P.trigger(this._element,xi,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(ki),this._adjustDialog(),this._backdrop.show((()=>this._showElement(t))))}hide(){this._isShown&&!this._isTransitioning&&(P.trigger(this._element,"hide.bs.modal").defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(Li),this._queueCallback((()=>this._hideModal()),this._element,this._isAnimated())))}dispose(){for(const t of[window,this._dialog])P.off(t,".bs.modal");this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new yi({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new Ci({trapElement:this._element})}_showElement(t){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const e=Q.findOne(".modal-body",this._dialog);e&&(e.scrollTop=0),d(this._element),this._element.classList.add(Li),this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,P.trigger(this._element,"shown.bs.modal",{relatedTarget:t})}),this._dialog,this._isAnimated())}_addEventListeners(){P.on(this._element,"keydown.dismiss.bs.modal",(t=>{if("Escape"===t.key)return this._config.keyboard?(t.preventDefault(),void this.hide()):void this._triggerBackdropTransition()})),P.on(window,"resize.bs.modal",(()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()})),P.on(this._element,"mousedown.dismiss.bs.modal",(t=>{P.one(this._element,"click.dismiss.bs.modal",(e=>{this._element===t.target&&this._element===e.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())}))}))}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(ki),this._resetAdjustments(),this._scrollBar.reset(),P.trigger(this._element,Oi)}))}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(P.trigger(this._element,"hidePrevented.bs.modal").defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._element.style.overflowY;"hidden"===e||this._element.classList.contains(Di)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(Di),this._queueCallback((()=>{this._element.classList.remove(Di),this._queueCallback((()=>{this._element.style.overflowY=e}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;if(i&&!t){const t=p()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!i&&t){const t=p()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=Ni.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}P.on(document,"click.bs.modal.data-api",'[data-bs-toggle="modal"]',(function(t){const e=n(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),P.one(e,xi,(t=>{t.defaultPrevented||P.one(e,Oi,(()=>{a(this)&&this.focus()}))}));const i=Q.findOne(".modal.show");i&&Ni.getInstance(i).hide(),Ni.getOrCreateInstance(e).toggle(this)})),q(Ni),g(Ni);const Pi="show",ji="showing",Mi="hiding",Hi=".offcanvas.show",$i="hidePrevented.bs.offcanvas",Wi="hidden.bs.offcanvas",Bi={backdrop:!0,keyboard:!0,scroll:!1},Fi={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class zi extends z{constructor(t,e){super(t,e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return Bi}static get DefaultType(){return Fi}static get NAME(){return"offcanvas"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||P.trigger(this._element,"show.bs.offcanvas",{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._backdrop.show(),this._config.scroll||(new gi).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(ji),this._queueCallback((()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(Pi),this._element.classList.remove(ji),P.trigger(this._element,"shown.bs.offcanvas",{relatedTarget:t})}),this._element,!0))}hide(){this._isShown&&(P.trigger(this._element,"hide.bs.offcanvas").defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add(Mi),this._backdrop.hide(),this._queueCallback((()=>{this._element.classList.remove(Pi,Mi),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new gi).reset(),P.trigger(this._element,Wi)}),this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const t=Boolean(this._config.backdrop);return new yi({className:"offcanvas-backdrop",isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?()=>{"static"!==this._config.backdrop?this.hide():P.trigger(this._element,$i)}:null})}_initializeFocusTrap(){return new Ci({trapElement:this._element})}_addEventListeners(){P.on(this._element,"keydown.dismiss.bs.offcanvas",(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():P.trigger(this._element,$i))}))}static jQueryInterface(t){return this.each((function(){const e=zi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}P.on(document,"click.bs.offcanvas.data-api",'[data-bs-toggle="offcanvas"]',(function(t){const e=n(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this))return;P.one(e,Wi,(()=>{a(this)&&this.focus()}));const i=Q.findOne(Hi);i&&i!==e&&zi.getInstance(i).hide(),zi.getOrCreateInstance(e).toggle(this)})),P.on(window,"load.bs.offcanvas.data-api",(()=>{for(const t of Q.find(Hi))zi.getOrCreateInstance(t).show()})),P.on(window,"resize.bs.offcanvas",(()=>{for(const t of Q.find("[aria-modal][class*=show][class*=offcanvas-]"))"fixed"!==getComputedStyle(t).position&&zi.getOrCreateInstance(t).hide()})),q(zi),g(zi);const qi=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Ri=/^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i,Vi=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i,Ki=(t,e)=>{const i=t.nodeName.toLowerCase();return e.includes(i)?!qi.has(i)||Boolean(Ri.test(t.nodeValue)||Vi.test(t.nodeValue)):e.filter((t=>t instanceof RegExp)).some((t=>t.test(i)))},Qi={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Xi={allowList:Qi,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
"},Yi={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},Ui={entry:"(string|element|function|null)",selector:"(string|element)"};class Gi extends F{constructor(t){super(),this._config=this._getConfig(t)}static get Default(){return Xi}static get DefaultType(){return Yi}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map((t=>this._resolvePossibleFunction(t))).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(t){return this._checkContent(t),this._config.content={...this._config.content,...t},this}toHtml(){const t=document.createElement("div");t.innerHTML=this._maybeSanitize(this._config.template);for(const[e,i]of Object.entries(this._config.content))this._setContent(t,i,e);const e=t.children[0],i=this._resolvePossibleFunction(this._config.extraClass);return i&&e.classList.add(...i.split(" ")),e}_typeCheckConfig(t){super._typeCheckConfig(t),this._checkContent(t.content)}_checkContent(t){for(const[e,i]of Object.entries(t))super._typeCheckConfig({selector:e,entry:i},Ui)}_setContent(t,e,i){const n=Q.findOne(i,t);n&&((e=this._resolvePossibleFunction(e))?o(e)?this._putElementInTemplate(r(e),n):this._config.html?n.innerHTML=this._maybeSanitize(e):n.textContent=e:n.remove())}_maybeSanitize(t){return this._config.sanitize?function(t,e,i){if(!t.length)return t;if(i&&"function"==typeof i)return i(t);const n=(new window.DOMParser).parseFromString(t,"text/html"),s=[].concat(...n.body.querySelectorAll("*"));for(const t of s){const i=t.nodeName.toLowerCase();if(!Object.keys(e).includes(i)){t.remove();continue}const n=[].concat(...t.attributes),s=[].concat(e["*"]||[],e[i]||[]);for(const e of n)Ki(e,s)||t.removeAttribute(e.nodeName)}return n.body.innerHTML}(t,this._config.allowList,this._config.sanitizeFn):t}_resolvePossibleFunction(t){return"function"==typeof t?t(this):t}_putElementInTemplate(t,e){if(this._config.html)return e.innerHTML="",void e.append(t);e.textContent=t.textContent}}const Ji=new Set(["sanitize","allowList","sanitizeFn"]),Zi="fade",tn="show",en=".modal",nn="hide.bs.modal",sn="hover",on="focus",rn={AUTO:"auto",TOP:"top",RIGHT:p()?"left":"right",BOTTOM:"bottom",LEFT:p()?"right":"left"},an={allowList:Qi,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,0],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},ln={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class cn extends z{constructor(t,e){if(void 0===Ke)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t,e),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return an}static get DefaultType(){return ln}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._activeTrigger.click=!this._activeTrigger.click,this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),P.off(this._element.closest(en),nn,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const t=P.trigger(this._element,this.constructor.eventName("show")),e=(c(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(t.defaultPrevented||!e)return;this._disposePopper();const i=this._getTipElement();this._element.setAttribute("aria-describedby",i.getAttribute("id"));const{container:n}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(n.append(i),P.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(i),i.classList.add(tn),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))P.on(t,"mouseover",h);this._queueCallback((()=>{P.trigger(this._element,this.constructor.eventName("shown")),!1===this._isHovered&&this._leave(),this._isHovered=!1}),this.tip,this._isAnimated())}hide(){if(this._isShown()&&!P.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented){if(this._getTipElement().classList.remove(tn),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))P.off(t,"mouseover",h);this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,this._isHovered=null,this._queueCallback((()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),P.trigger(this._element,this.constructor.eventName("hidden")))}),this.tip,this._isAnimated())}}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(t){const e=this._getTemplateFactory(t).toHtml();if(!e)return null;e.classList.remove(Zi,tn),e.classList.add(`bs-${this.constructor.NAME}-auto`);const i=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME).toString();return e.setAttribute("id",i),this._isAnimated()&&e.classList.add(Zi),e}setContent(t){this._newContent=t,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(t){return this._templateFactory?this._templateFactory.changeContent(t):this._templateFactory=new Gi({...this._config,content:t,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{".tooltip-inner":this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(t){return this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(Zi)}_isShown(){return this.tip&&this.tip.classList.contains(tn)}_createPopper(t){const e="function"==typeof this._config.placement?this._config.placement.call(this,t,this._element):this._config.placement,i=rn[e.toUpperCase()];return Ve(this._element,t,this._getPopperConfig(i))}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return"function"==typeof t?t.call(this._element):t}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:t=>{this._getTipElement().setAttribute("data-popper-placement",t.state.placement)}}]};return{...e,..."function"==typeof this._config.popperConfig?this._config.popperConfig(e):this._config.popperConfig}}_setListeners(){const t=this._config.trigger.split(" ");for(const e of t)if("click"===e)P.on(this._element,this.constructor.eventName("click"),this._config.selector,(t=>{this._initializeOnDelegatedTarget(t).toggle()}));else if("manual"!==e){const t=e===sn?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),i=e===sn?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");P.on(this._element,t,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusin"===t.type?on:sn]=!0,e._enter()})),P.on(this._element,i,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusout"===t.type?on:sn]=e._element.contains(t.relatedTarget),e._leave()}))}this._hideModalHandler=()=>{this._element&&this.hide()},P.on(this._element.closest(en),nn,this._hideModalHandler)}_fixTitle(){const t=this._element.getAttribute("title");t&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",t),this._element.setAttribute("data-bs-original-title",t),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout((()=>{this._isHovered&&this.show()}),this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout((()=>{this._isHovered||this.hide()}),this._config.delay.hide))}_setTimeout(t,e){clearTimeout(this._timeout),this._timeout=setTimeout(t,e)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(t){const e=B.getDataAttributes(this._element);for(const t of Object.keys(e))Ji.has(t)&&delete e[t];return t={...e,..."object"==typeof t&&t?t:{}},t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t.container=!1===t.container?document.body:r(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),t}_getDelegateConfig(){const t={};for(const e in this._config)this.constructor.Default[e]!==this._config[e]&&(t[e]=this._config[e]);return t.selector=!1,t.trigger="manual",t}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(t){return this.each((function(){const e=cn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}g(cn);const hn={...cn.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},dn={...cn.DefaultType,content:"(null|string|element|function)"};class un extends cn{static get Default(){return hn}static get DefaultType(){return dn}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{".popover-header":this._getTitle(),".popover-body":this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(t){return this.each((function(){const e=un.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}g(un);const fn="click.bs.scrollspy",pn="active",gn="[href]",mn={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},_n={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class bn extends z{constructor(t,e){super(t,e),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement="visible"===getComputedStyle(this._element).overflowY?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return mn}static get DefaultType(){return _n}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const t of this._observableSections.values())this._observer.observe(t)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(t){return t.target=r(t.target)||document.body,t.rootMargin=t.offset?`${t.offset}px 0px -30%`:t.rootMargin,"string"==typeof t.threshold&&(t.threshold=t.threshold.split(",").map((t=>Number.parseFloat(t)))),t}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(P.off(this._config.target,fn),P.on(this._config.target,fn,gn,(t=>{const e=this._observableSections.get(t.target.hash);if(e){t.preventDefault();const i=this._rootElement||window,n=e.offsetTop-this._element.offsetTop;if(i.scrollTo)return void i.scrollTo({top:n,behavior:"smooth"});i.scrollTop=n}})))}_getNewObserver(){const t={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver((t=>this._observerCallback(t)),t)}_observerCallback(t){const e=t=>this._targetLinks.get(`#${t.target.id}`),i=t=>{this._previousScrollData.visibleEntryTop=t.target.offsetTop,this._process(e(t))},n=(this._rootElement||document.documentElement).scrollTop,s=n>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=n;for(const o of t){if(!o.isIntersecting){this._activeTarget=null,this._clearActiveClass(e(o));continue}const t=o.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(s&&t){if(i(o),!n)return}else s||t||i(o)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const t=Q.find(gn,this._config.target);for(const e of t){if(!e.hash||l(e))continue;const t=Q.findOne(e.hash,this._element);a(t)&&(this._targetLinks.set(e.hash,e),this._observableSections.set(e.hash,t))}}_process(t){this._activeTarget!==t&&(this._clearActiveClass(this._config.target),this._activeTarget=t,t.classList.add(pn),this._activateParents(t),P.trigger(this._element,"activate.bs.scrollspy",{relatedTarget:t}))}_activateParents(t){if(t.classList.contains("dropdown-item"))Q.findOne(".dropdown-toggle",t.closest(".dropdown")).classList.add(pn);else for(const e of Q.parents(t,".nav, .list-group"))for(const t of Q.prev(e,".nav-link, .nav-item > .nav-link, .list-group-item"))t.classList.add(pn)}_clearActiveClass(t){t.classList.remove(pn);const e=Q.find("[href].active",t);for(const t of e)t.classList.remove(pn)}static jQueryInterface(t){return this.each((function(){const e=bn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}P.on(window,"load.bs.scrollspy.data-api",(()=>{for(const t of Q.find('[data-bs-spy="scroll"]'))bn.getOrCreateInstance(t)})),g(bn);const vn="ArrowLeft",yn="ArrowRight",wn="ArrowUp",An="ArrowDown",En="active",Tn="fade",Cn="show",On='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',xn=`.nav-link:not(.dropdown-toggle), .list-group-item:not(.dropdown-toggle), [role="tab"]:not(.dropdown-toggle), ${On}`;class kn extends z{constructor(t){super(t),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),P.on(this._element,"keydown.bs.tab",(t=>this._keydown(t))))}static get NAME(){return"tab"}show(){const t=this._element;if(this._elemIsActive(t))return;const e=this._getActiveElem(),i=e?P.trigger(e,"hide.bs.tab",{relatedTarget:t}):null;P.trigger(t,"show.bs.tab",{relatedTarget:e}).defaultPrevented||i&&i.defaultPrevented||(this._deactivate(e,t),this._activate(t,e))}_activate(t,e){t&&(t.classList.add(En),this._activate(n(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.removeAttribute("tabindex"),t.setAttribute("aria-selected",!0),this._toggleDropDown(t,!0),P.trigger(t,"shown.bs.tab",{relatedTarget:e})):t.classList.add(Cn)}),t,t.classList.contains(Tn)))}_deactivate(t,e){t&&(t.classList.remove(En),t.blur(),this._deactivate(n(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.setAttribute("aria-selected",!1),t.setAttribute("tabindex","-1"),this._toggleDropDown(t,!1),P.trigger(t,"hidden.bs.tab",{relatedTarget:e})):t.classList.remove(Cn)}),t,t.classList.contains(Tn)))}_keydown(t){if(![vn,yn,wn,An].includes(t.key))return;t.stopPropagation(),t.preventDefault();const e=[yn,An].includes(t.key),i=b(this._getChildren().filter((t=>!l(t))),t.target,e,!0);i&&(i.focus({preventScroll:!0}),kn.getOrCreateInstance(i).show())}_getChildren(){return Q.find(xn,this._parent)}_getActiveElem(){return this._getChildren().find((t=>this._elemIsActive(t)))||null}_setInitialAttributes(t,e){this._setAttributeIfNotExists(t,"role","tablist");for(const t of e)this._setInitialAttributesOnChild(t)}_setInitialAttributesOnChild(t){t=this._getInnerElement(t);const e=this._elemIsActive(t),i=this._getOuterElement(t);t.setAttribute("aria-selected",e),i!==t&&this._setAttributeIfNotExists(i,"role","presentation"),e||t.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(t,"role","tab"),this._setInitialAttributesOnTargetPanel(t)}_setInitialAttributesOnTargetPanel(t){const e=n(t);e&&(this._setAttributeIfNotExists(e,"role","tabpanel"),t.id&&this._setAttributeIfNotExists(e,"aria-labelledby",`#${t.id}`))}_toggleDropDown(t,e){const i=this._getOuterElement(t);if(!i.classList.contains("dropdown"))return;const n=(t,n)=>{const s=Q.findOne(t,i);s&&s.classList.toggle(n,e)};n(".dropdown-toggle",En),n(".dropdown-menu",Cn),i.setAttribute("aria-expanded",e)}_setAttributeIfNotExists(t,e,i){t.hasAttribute(e)||t.setAttribute(e,i)}_elemIsActive(t){return t.classList.contains(En)}_getInnerElement(t){return t.matches(xn)?t:Q.findOne(xn,t)}_getOuterElement(t){return t.closest(".nav-item, .list-group-item")||t}static jQueryInterface(t){return this.each((function(){const e=kn.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}P.on(document,"click.bs.tab",On,(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this)||kn.getOrCreateInstance(this).show()})),P.on(window,"load.bs.tab",(()=>{for(const t of Q.find('.active[data-bs-toggle="tab"], .active[data-bs-toggle="pill"], .active[data-bs-toggle="list"]'))kn.getOrCreateInstance(t)})),g(kn);const Ln="hide",Dn="show",Sn="showing",In={animation:"boolean",autohide:"boolean",delay:"number"},Nn={animation:!0,autohide:!0,delay:5e3};class Pn extends z{constructor(t,e){super(t,e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return Nn}static get DefaultType(){return In}static get NAME(){return"toast"}show(){P.trigger(this._element,"show.bs.toast").defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(Ln),d(this._element),this._element.classList.add(Dn,Sn),this._queueCallback((()=>{this._element.classList.remove(Sn),P.trigger(this._element,"shown.bs.toast"),this._maybeScheduleHide()}),this._element,this._config.animation))}hide(){this.isShown()&&(P.trigger(this._element,"hide.bs.toast").defaultPrevented||(this._element.classList.add(Sn),this._queueCallback((()=>{this._element.classList.add(Ln),this._element.classList.remove(Sn,Dn),P.trigger(this._element,"hidden.bs.toast")}),this._element,this._config.animation)))}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(Dn),super.dispose()}isShown(){return this._element.classList.contains(Dn)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){P.on(this._element,"mouseover.bs.toast",(t=>this._onInteraction(t,!0))),P.on(this._element,"mouseout.bs.toast",(t=>this._onInteraction(t,!1))),P.on(this._element,"focusin.bs.toast",(t=>this._onInteraction(t,!0))),P.on(this._element,"focusout.bs.toast",(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=Pn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return q(Pn),g(Pn),{Alert:R,Button:K,Carousel:at,Collapse:pt,Dropdown:hi,Modal:Ni,Offcanvas:zi,Popover:un,ScrollSpy:bn,Tab:kn,Toast:Pn,Tooltip:cn}})); +//# sourceMappingURL=bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/django/Invoice/static/bootstrap.min.css b/django/Invoice/static/bootstrap.min.css new file mode 100644 index 0000000..f06f523 --- /dev/null +++ b/django/Invoice/static/bootstrap.min.css @@ -0,0 +1,7 @@ +@charset "UTF-8";/*! + * Bootstrap v5.2.3 (https://getbootstrap.com/) + * Copyright 2011-2022 The Bootstrap Authors + * Copyright 2011-2022 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-body-color-rgb:33,37,41;--bs-body-bg-rgb:255,255,255;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-bg:#fff;--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0, 0, 0, 0.175);--bs-border-radius:0.375rem;--bs-border-radius-sm:0.25rem;--bs-border-radius-lg:0.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-2xl:2rem;--bs-border-radius-pill:50rem;--bs-link-color:#0d6efd;--bs-link-hover-color:#0a58ca;--bs-code-color:#d63384;--bs-highlight-bg:#fff3cd}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;border:0;border-top:1px solid;opacity:.25}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.1875em;background-color:var(--bs-highlight-bg)}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:var(--bs-link-color);text-decoration:underline}a:hover{color:var(--bs-link-hover-color)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:var(--bs-code-color);word-wrap:break-word}a>code{color:inherit}kbd{padding:.1875rem .375rem;font-size:.875em;color:var(--bs-body-bg);background-color:var(--bs-body-color);border-radius:.25rem}kbd kbd{padding:0;font-size:1em}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none!important}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}::file-selector-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid var(--bs-border-color);border-radius:.375rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:#6c757d}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{--bs-gutter-x:1.5rem;--bs-gutter-y:0;width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}@media (min-width:1400px){.container,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{max-width:1320px}}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(-1 * var(--bs-gutter-y));margin-right:calc(-.5 * var(--bs-gutter-x));margin-left:calc(-.5 * var(--bs-gutter-x))}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-top:var(--bs-gutter-y)}.col{flex:1 0 0%}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.6666666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.33333333%}.col-2{flex:0 0 auto;width:16.66666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.33333333%}.col-5{flex:0 0 auto;width:41.66666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.33333333%}.col-8{flex:0 0 auto;width:66.66666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.33333333%}.col-11{flex:0 0 auto;width:91.66666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}.g-0,.gx-0{--bs-gutter-x:0}.g-0,.gy-0{--bs-gutter-y:0}.g-1,.gx-1{--bs-gutter-x:0.25rem}.g-1,.gy-1{--bs-gutter-y:0.25rem}.g-2,.gx-2{--bs-gutter-x:0.5rem}.g-2,.gy-2{--bs-gutter-y:0.5rem}.g-3,.gx-3{--bs-gutter-x:1rem}.g-3,.gy-3{--bs-gutter-y:1rem}.g-4,.gx-4{--bs-gutter-x:1.5rem}.g-4,.gy-4{--bs-gutter-y:1.5rem}.g-5,.gx-5{--bs-gutter-x:3rem}.g-5,.gy-5{--bs-gutter-y:3rem}@media (min-width:576px){.col-sm{flex:1 0 0%}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.6666666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.33333333%}.col-sm-2{flex:0 0 auto;width:16.66666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.33333333%}.col-sm-5{flex:0 0 auto;width:41.66666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.33333333%}.col-sm-8{flex:0 0 auto;width:66.66666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.33333333%}.col-sm-11{flex:0 0 auto;width:91.66666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x:0}.g-sm-0,.gy-sm-0{--bs-gutter-y:0}.g-sm-1,.gx-sm-1{--bs-gutter-x:0.25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y:0.25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x:0.5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y:0.5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x:1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y:1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x:1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y:1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x:3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y:3rem}}@media (min-width:768px){.col-md{flex:1 0 0%}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.6666666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.33333333%}.col-md-2{flex:0 0 auto;width:16.66666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-5{flex:0 0 auto;width:41.66666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-11{flex:0 0 auto;width:91.66666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}.g-md-0,.gx-md-0{--bs-gutter-x:0}.g-md-0,.gy-md-0{--bs-gutter-y:0}.g-md-1,.gx-md-1{--bs-gutter-x:0.25rem}.g-md-1,.gy-md-1{--bs-gutter-y:0.25rem}.g-md-2,.gx-md-2{--bs-gutter-x:0.5rem}.g-md-2,.gy-md-2{--bs-gutter-y:0.5rem}.g-md-3,.gx-md-3{--bs-gutter-x:1rem}.g-md-3,.gy-md-3{--bs-gutter-y:1rem}.g-md-4,.gx-md-4{--bs-gutter-x:1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y:1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x:3rem}.g-md-5,.gy-md-5{--bs-gutter-y:3rem}}@media (min-width:992px){.col-lg{flex:1 0 0%}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.6666666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.33333333%}.col-lg-2{flex:0 0 auto;width:16.66666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.33333333%}.col-lg-11{flex:0 0 auto;width:91.66666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x:0}.g-lg-0,.gy-lg-0{--bs-gutter-y:0}.g-lg-1,.gx-lg-1{--bs-gutter-x:0.25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y:0.25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x:0.5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y:0.5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x:1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y:1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x:1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y:1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x:3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y:3rem}}@media (min-width:1200px){.col-xl{flex:1 0 0%}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.33333333%}.col-xl-2{flex:0 0 auto;width:16.66666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.33333333%}.col-xl-5{flex:0 0 auto;width:41.66666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.33333333%}.col-xl-8{flex:0 0 auto;width:66.66666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.33333333%}.col-xl-11{flex:0 0 auto;width:91.66666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x:0}.g-xl-0,.gy-xl-0{--bs-gutter-y:0}.g-xl-1,.gx-xl-1{--bs-gutter-x:0.25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y:0.25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x:0.5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y:0.5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x:1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y:1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x:1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y:1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x:3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y:3rem}}@media (min-width:1400px){.col-xxl{flex:1 0 0%}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.33333333%}.col-xxl-2{flex:0 0 auto;width:16.66666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.33333333%}.col-xxl-5{flex:0 0 auto;width:41.66666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.33333333%}.col-xxl-8{flex:0 0 auto;width:66.66666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.33333333%}.col-xxl-11{flex:0 0 auto;width:91.66666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x:0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y:0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x:0.25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y:0.25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x:0.5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y:0.5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x:1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y:1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x:1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y:1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x:3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y:3rem}}.table{--bs-table-color:var(--bs-body-color);--bs-table-bg:transparent;--bs-table-border-color:var(--bs-border-color);--bs-table-accent-bg:transparent;--bs-table-striped-color:var(--bs-body-color);--bs-table-striped-bg:rgba(0, 0, 0, 0.05);--bs-table-active-color:var(--bs-body-color);--bs-table-active-bg:rgba(0, 0, 0, 0.1);--bs-table-hover-color:var(--bs-body-color);--bs-table-hover-bg:rgba(0, 0, 0, 0.075);width:100%;margin-bottom:1rem;color:var(--bs-table-color);vertical-align:top;border-color:var(--bs-table-border-color)}.table>:not(caption)>*>*{padding:.5rem .5rem;background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-accent-bg)}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table-group-divider{border-top:2px solid currentcolor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-accent-bg:var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-striped-columns>:not(caption)>tr>:nth-child(2n){--bs-table-accent-bg:var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-active{--bs-table-accent-bg:var(--bs-table-active-bg);color:var(--bs-table-active-color)}.table-hover>tbody>tr:hover>*{--bs-table-accent-bg:var(--bs-table-hover-bg);color:var(--bs-table-hover-color)}.table-primary{--bs-table-color:#000;--bs-table-bg:#cfe2ff;--bs-table-border-color:#bacbe6;--bs-table-striped-bg:#c5d7f2;--bs-table-striped-color:#000;--bs-table-active-bg:#bacbe6;--bs-table-active-color:#000;--bs-table-hover-bg:#bfd1ec;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-secondary{--bs-table-color:#000;--bs-table-bg:#e2e3e5;--bs-table-border-color:#cbccce;--bs-table-striped-bg:#d7d8da;--bs-table-striped-color:#000;--bs-table-active-bg:#cbccce;--bs-table-active-color:#000;--bs-table-hover-bg:#d1d2d4;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-success{--bs-table-color:#000;--bs-table-bg:#d1e7dd;--bs-table-border-color:#bcd0c7;--bs-table-striped-bg:#c7dbd2;--bs-table-striped-color:#000;--bs-table-active-bg:#bcd0c7;--bs-table-active-color:#000;--bs-table-hover-bg:#c1d6cc;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-info{--bs-table-color:#000;--bs-table-bg:#cff4fc;--bs-table-border-color:#badce3;--bs-table-striped-bg:#c5e8ef;--bs-table-striped-color:#000;--bs-table-active-bg:#badce3;--bs-table-active-color:#000;--bs-table-hover-bg:#bfe2e9;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-warning{--bs-table-color:#000;--bs-table-bg:#fff3cd;--bs-table-border-color:#e6dbb9;--bs-table-striped-bg:#f2e7c3;--bs-table-striped-color:#000;--bs-table-active-bg:#e6dbb9;--bs-table-active-color:#000;--bs-table-hover-bg:#ece1be;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-danger{--bs-table-color:#000;--bs-table-bg:#f8d7da;--bs-table-border-color:#dfc2c4;--bs-table-striped-bg:#eccccf;--bs-table-striped-color:#000;--bs-table-active-bg:#dfc2c4;--bs-table-active-color:#000;--bs-table-hover-bg:#e5c7ca;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-light{--bs-table-color:#000;--bs-table-bg:#f8f9fa;--bs-table-border-color:#dfe0e1;--bs-table-striped-bg:#ecedee;--bs-table-striped-color:#000;--bs-table-active-bg:#dfe0e1;--bs-table-active-color:#000;--bs-table-hover-bg:#e5e6e7;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-dark{--bs-table-color:#fff;--bs-table-bg:#212529;--bs-table-border-color:#373b3e;--bs-table-striped-bg:#2c3034;--bs-table-striped-color:#fff;--bs-table-active-bg:#373b3e;--bs-table-active-color:#fff;--bs-table-hover-bg:#323539;--bs-table-hover-color:#fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media (max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:#6c757d}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:#212529;background-color:#fff;border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-control::-webkit-date-and-time-value{height:1.5em}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled{background-color:#e9ecef;opacity:1}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:#212529;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:#212529;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::-webkit-file-upload-button{-webkit-transition:none;transition:none}.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:#dde0e3}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#dde0e3}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext:focus{outline:0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;border-radius:.25rem}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;border-radius:.5rem}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + .75rem + 2px)}textarea.form-control-sm{min-height:calc(1.5em + .5rem + 2px)}textarea.form-control-lg{min-height:calc(1.5em + 1rem + 2px)}.form-control-color{width:3rem;height:calc(1.5em + .75rem + 2px);padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0!important;border-radius:.375rem}.form-control-color::-webkit-color-swatch{border-radius:.375rem}.form-control-color.form-control-sm{height:calc(1.5em + .5rem + 2px)}.form-control-color.form-control-lg{height:calc(1.5em + 1rem + 2px)}.form-select{display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;-moz-padding-start:calc(0.75rem - 3px);font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid #ced4da;border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:#e9ecef}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #212529}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem;border-radius:.25rem}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem;border-radius:.5rem}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-reverse{padding-right:1.5em;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:-1.5em;margin-left:0}.form-check-input{width:1em;height:1em;margin-top:.25em;vertical-align:top;background-color:#fff;background-repeat:no-repeat;background-position:center;background-size:contain;border:1px solid rgba(0,0,0,.25);-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-print-color-adjust:exact;color-adjust:exact;print-color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#0d6efd;border-color:#0d6efd;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{cursor:default;opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{width:2em;margin-left:-2.5em;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-switch.form-check-reverse{padding-right:2.5em;padding-left:0}.form-switch.form-check-reverse .form-check-input{margin-right:-2.5em;margin-left:0}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check:disabled+.btn,.btn-check[disabled]+.btn{pointer-events:none;filter:none;opacity:.65}.form-range{width:100%;height:1.5rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#0d6efd;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b6d4fe}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#0d6efd;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{-moz-transition:none;transition:none}}.form-range::-moz-range-thumb:active{background-color:#b6d4fe}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.form-range:disabled::-moz-range-thumb{background-color:#adb5bd}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + 2px);line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;width:100%;height:100%;padding:1rem .75rem;overflow:hidden;text-align:start;text-overflow:ellipsis;white-space:nowrap;pointer-events:none;border:1px solid transparent;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem .75rem}.form-floating>.form-control-plaintext::-moz-placeholder,.form-floating>.form-control::-moz-placeholder{color:transparent}.form-floating>.form-control-plaintext::placeholder,.form-floating>.form-control::placeholder{color:transparent}.form-floating>.form-control-plaintext:not(:-moz-placeholder-shown),.form-floating>.form-control:not(:-moz-placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown),.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control-plaintext:-webkit-autofill,.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:not(:-moz-placeholder-shown)~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control-plaintext~label,.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:-webkit-autofill~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control-plaintext~label{border-width:1px 0}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-floating,.input-group>.form-select{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-floating:focus-within,.input-group>.form-select:focus{z-index:5}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:5}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.375rem}.input-group-lg>.btn,.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;border-radius:.5rem}.input-group-sm>.btn,.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text{padding:.25rem .5rem;font-size:.875rem;border-radius:.25rem}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select,.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select,.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:-1px;border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select{border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#198754}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(25,135,84,.9);border-radius:.375rem}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#198754;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-valid,.was-validated .form-select:valid{border-color:#198754}.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"],.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-valid:focus,.was-validated .form-select:valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.form-control-color.is-valid,.was-validated .form-control-color:valid{width:calc(3rem + calc(1.5em + .75rem))}.form-check-input.is-valid,.was-validated .form-check-input:valid{border-color:#198754}.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked{background-color:#198754}.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#198754}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-valid,.input-group>.form-floating:not(:focus-within).is-valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-control:not(:focus):valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.was-validated .input-group>.form-select:not(:focus):valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.375rem}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-invalid,.was-validated .form-select:invalid{border-color:#dc3545}.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-invalid:focus,.was-validated .form-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.form-control-color.is-invalid,.was-validated .form-control-color:invalid{width:calc(3rem + calc(1.5em + .75rem))}.form-check-input.is-invalid,.was-validated .form-check-input:invalid{border-color:#dc3545}.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked{background-color:#dc3545}.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-invalid,.input-group>.form-floating:not(:focus-within).is-invalid,.input-group>.form-select:not(:focus).is-invalid,.was-validated .input-group>.form-control:not(:focus):invalid,.was-validated .input-group>.form-floating:not(:focus-within):invalid,.was-validated .input-group>.form-select:not(:focus):invalid{z-index:4}.btn{--bs-btn-padding-x:0.75rem;--bs-btn-padding-y:0.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight:400;--bs-btn-line-height:1.5;--bs-btn-color:#212529;--bs-btn-bg:transparent;--bs-btn-border-width:1px;--bs-btn-border-color:transparent;--bs-btn-border-radius:0.375rem;--bs-btn-hover-border-color:transparent;--bs-btn-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.15),0 1px 1px rgba(0, 0, 0, 0.075);--bs-btn-disabled-opacity:0.65;--bs-btn-focus-box-shadow:0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color)}.btn-check+.btn:hover{color:var(--bs-btn-color);background-color:var(--bs-btn-bg);border-color:var(--bs-btn-border-color)}.btn:focus-visible{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:focus-visible+.btn{border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:checked+.btn,.btn.active,.btn.show,.btn:first-child:active,:not(.btn-check)+.btn:active{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color)}.btn-check:checked+.btn:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible,.btn:first-child:active:focus-visible,:not(.btn-check)+.btn:active:focus-visible{box-shadow:var(--bs-btn-focus-box-shadow)}.btn.disabled,.btn:disabled,fieldset:disabled .btn{color:var(--bs-btn-disabled-color);pointer-events:none;background-color:var(--bs-btn-disabled-bg);border-color:var(--bs-btn-disabled-border-color);opacity:var(--bs-btn-disabled-opacity)}.btn-primary{--bs-btn-color:#fff;--bs-btn-bg:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#0b5ed7;--bs-btn-hover-border-color:#0a58ca;--bs-btn-focus-shadow-rgb:49,132,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:#0a58ca;--bs-btn-active-border-color:#0a53be;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#0d6efd;--bs-btn-disabled-border-color:#0d6efd}.btn-secondary{--bs-btn-color:#fff;--bs-btn-bg:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#5c636a;--bs-btn-hover-border-color:#565e64;--bs-btn-focus-shadow-rgb:130,138,145;--bs-btn-active-color:#fff;--bs-btn-active-bg:#565e64;--bs-btn-active-border-color:#51585e;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#6c757d;--bs-btn-disabled-border-color:#6c757d}.btn-success{--bs-btn-color:#fff;--bs-btn-bg:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#157347;--bs-btn-hover-border-color:#146c43;--bs-btn-focus-shadow-rgb:60,153,110;--bs-btn-active-color:#fff;--bs-btn-active-bg:#146c43;--bs-btn-active-border-color:#13653f;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#198754;--bs-btn-disabled-border-color:#198754}.btn-info{--bs-btn-color:#000;--bs-btn-bg:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#31d2f2;--bs-btn-hover-border-color:#25cff2;--bs-btn-focus-shadow-rgb:11,172,204;--bs-btn-active-color:#000;--bs-btn-active-bg:#3dd5f3;--bs-btn-active-border-color:#25cff2;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#0dcaf0;--bs-btn-disabled-border-color:#0dcaf0}.btn-warning{--bs-btn-color:#000;--bs-btn-bg:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ffca2c;--bs-btn-hover-border-color:#ffc720;--bs-btn-focus-shadow-rgb:217,164,6;--bs-btn-active-color:#000;--bs-btn-active-bg:#ffcd39;--bs-btn-active-border-color:#ffc720;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#ffc107;--bs-btn-disabled-border-color:#ffc107}.btn-danger{--bs-btn-color:#fff;--bs-btn-bg:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#bb2d3b;--bs-btn-hover-border-color:#b02a37;--bs-btn-focus-shadow-rgb:225,83,97;--bs-btn-active-color:#fff;--bs-btn-active-bg:#b02a37;--bs-btn-active-border-color:#a52834;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#dc3545;--bs-btn-disabled-border-color:#dc3545}.btn-light{--bs-btn-color:#000;--bs-btn-bg:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#d3d4d5;--bs-btn-hover-border-color:#c6c7c8;--bs-btn-focus-shadow-rgb:211,212,213;--bs-btn-active-color:#000;--bs-btn-active-bg:#c6c7c8;--bs-btn-active-border-color:#babbbc;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#f8f9fa;--bs-btn-disabled-border-color:#f8f9fa}.btn-dark{--bs-btn-color:#fff;--bs-btn-bg:#212529;--bs-btn-border-color:#212529;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#424649;--bs-btn-hover-border-color:#373b3e;--bs-btn-focus-shadow-rgb:66,70,73;--bs-btn-active-color:#fff;--bs-btn-active-bg:#4d5154;--bs-btn-active-border-color:#373b3e;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#212529;--bs-btn-disabled-border-color:#212529}.btn-outline-primary{--bs-btn-color:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#0d6efd;--bs-btn-hover-border-color:#0d6efd;--bs-btn-focus-shadow-rgb:13,110,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:#0d6efd;--bs-btn-active-border-color:#0d6efd;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#0d6efd;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#0d6efd;--bs-gradient:none}.btn-outline-secondary{--bs-btn-color:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#6c757d;--bs-btn-hover-border-color:#6c757d;--bs-btn-focus-shadow-rgb:108,117,125;--bs-btn-active-color:#fff;--bs-btn-active-bg:#6c757d;--bs-btn-active-border-color:#6c757d;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#6c757d;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#6c757d;--bs-gradient:none}.btn-outline-success{--bs-btn-color:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#198754;--bs-btn-hover-border-color:#198754;--bs-btn-focus-shadow-rgb:25,135,84;--bs-btn-active-color:#fff;--bs-btn-active-bg:#198754;--bs-btn-active-border-color:#198754;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#198754;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#198754;--bs-gradient:none}.btn-outline-info{--bs-btn-color:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#0dcaf0;--bs-btn-hover-border-color:#0dcaf0;--bs-btn-focus-shadow-rgb:13,202,240;--bs-btn-active-color:#000;--bs-btn-active-bg:#0dcaf0;--bs-btn-active-border-color:#0dcaf0;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#0dcaf0;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#0dcaf0;--bs-gradient:none}.btn-outline-warning{--bs-btn-color:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ffc107;--bs-btn-hover-border-color:#ffc107;--bs-btn-focus-shadow-rgb:255,193,7;--bs-btn-active-color:#000;--bs-btn-active-bg:#ffc107;--bs-btn-active-border-color:#ffc107;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#ffc107;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#ffc107;--bs-gradient:none}.btn-outline-danger{--bs-btn-color:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#dc3545;--bs-btn-hover-border-color:#dc3545;--bs-btn-focus-shadow-rgb:220,53,69;--bs-btn-active-color:#fff;--bs-btn-active-bg:#dc3545;--bs-btn-active-border-color:#dc3545;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#dc3545;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#dc3545;--bs-gradient:none}.btn-outline-light{--bs-btn-color:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#f8f9fa;--bs-btn-hover-border-color:#f8f9fa;--bs-btn-focus-shadow-rgb:248,249,250;--bs-btn-active-color:#000;--bs-btn-active-bg:#f8f9fa;--bs-btn-active-border-color:#f8f9fa;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#f8f9fa;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#f8f9fa;--bs-gradient:none}.btn-outline-dark{--bs-btn-color:#212529;--bs-btn-border-color:#212529;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#212529;--bs-btn-hover-border-color:#212529;--bs-btn-focus-shadow-rgb:33,37,41;--bs-btn-active-color:#fff;--bs-btn-active-bg:#212529;--bs-btn-active-border-color:#212529;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#212529;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#212529;--bs-gradient:none}.btn-link{--bs-btn-font-weight:400;--bs-btn-color:var(--bs-link-color);--bs-btn-bg:transparent;--bs-btn-border-color:transparent;--bs-btn-hover-color:var(--bs-link-hover-color);--bs-btn-hover-border-color:transparent;--bs-btn-active-color:var(--bs-link-hover-color);--bs-btn-active-border-color:transparent;--bs-btn-disabled-color:#6c757d;--bs-btn-disabled-border-color:transparent;--bs-btn-box-shadow:none;--bs-btn-focus-shadow-rgb:49,132,253;text-decoration:underline}.btn-link:focus-visible{color:var(--bs-btn-color)}.btn-link:hover{color:var(--bs-btn-hover-color)}.btn-group-lg>.btn,.btn-lg{--bs-btn-padding-y:0.5rem;--bs-btn-padding-x:1rem;--bs-btn-font-size:1.25rem;--bs-btn-border-radius:0.5rem}.btn-group-sm>.btn,.btn-sm{--bs-btn-padding-y:0.25rem;--bs-btn-padding-x:0.5rem;--bs-btn-font-size:0.875rem;--bs-btn-border-radius:0.25rem}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.collapse-horizontal{transition:none}}.dropdown,.dropdown-center,.dropend,.dropstart,.dropup,.dropup-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{--bs-dropdown-zindex:1000;--bs-dropdown-min-width:10rem;--bs-dropdown-padding-x:0;--bs-dropdown-padding-y:0.5rem;--bs-dropdown-spacer:0.125rem;--bs-dropdown-font-size:1rem;--bs-dropdown-color:#212529;--bs-dropdown-bg:#fff;--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-border-radius:0.375rem;--bs-dropdown-border-width:1px;--bs-dropdown-inner-border-radius:calc(0.375rem - 1px);--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-divider-margin-y:0.5rem;--bs-dropdown-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-dropdown-link-color:#212529;--bs-dropdown-link-hover-color:#1e2125;--bs-dropdown-link-hover-bg:#e9ecef;--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#0d6efd;--bs-dropdown-link-disabled-color:#adb5bd;--bs-dropdown-item-padding-x:1rem;--bs-dropdown-item-padding-y:0.25rem;--bs-dropdown-header-color:#6c757d;--bs-dropdown-header-padding-x:1rem;--bs-dropdown-header-padding-y:0.5rem;position:absolute;z-index:var(--bs-dropdown-zindex);display:none;min-width:var(--bs-dropdown-min-width);padding:var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x);margin:0;font-size:var(--bs-dropdown-font-size);color:var(--bs-dropdown-color);text-align:left;list-style:none;background-color:var(--bs-dropdown-bg);background-clip:padding-box;border:var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color);border-radius:var(--bs-dropdown-border-radius)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:var(--bs-dropdown-spacer)}.dropdown-menu-start{--bs-position:start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position:end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-start{--bs-position:start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position:end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-start{--bs-position:start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position:end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-start{--bs-position:start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position:end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-start{--bs-position:start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position:end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1400px){.dropdown-menu-xxl-start{--bs-position:start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position:end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:var(--bs-dropdown-spacer)}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:var(--bs-dropdown-spacer)}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:var(--bs-dropdown-spacer)}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:var(--bs-dropdown-divider-margin-y) 0;overflow:hidden;border-top:1px solid var(--bs-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--bs-dropdown-link-color);text-align:inherit;text-decoration:none;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-item:active{color:var(--bs-dropdown-link-active-color);text-decoration:none;background-color:var(--bs-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-item:disabled{color:var(--bs-dropdown-link-disabled-color);pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x);margin-bottom:0;font-size:.875rem;color:var(--bs-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);color:var(--bs-dropdown-link-color)}.dropdown-menu-dark{--bs-dropdown-color:#dee2e6;--bs-dropdown-bg:#343a40;--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-box-shadow: ;--bs-dropdown-link-color:#dee2e6;--bs-dropdown-link-hover-color:#fff;--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-link-hover-bg:rgba(255, 255, 255, 0.15);--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#0d6efd;--bs-dropdown-link-disabled-color:#adb5bd;--bs-dropdown-header-color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group{border-radius:.375rem}.btn-group>.btn-group:not(:first-child),.btn-group>:not(.btn-check:first-child)+.btn{margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn.dropdown-toggle-split:first-child,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn~.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{--bs-nav-link-padding-x:1rem;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-link-color);--bs-nav-link-hover-color:var(--bs-link-hover-color);--bs-nav-link-disabled-color:#6c757d;display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);color:var(--bs-nav-link-color);text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:var(--bs-nav-link-hover-color)}.nav-link.disabled{color:var(--bs-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--bs-nav-tabs-border-width:1px;--bs-nav-tabs-border-color:#dee2e6;--bs-nav-tabs-border-radius:0.375rem;--bs-nav-tabs-link-hover-border-color:#e9ecef #e9ecef #dee2e6;--bs-nav-tabs-link-active-color:#495057;--bs-nav-tabs-link-active-bg:#fff;--bs-nav-tabs-link-active-border-color:#dee2e6 #dee2e6 #fff;border-bottom:var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color)}.nav-tabs .nav-link{margin-bottom:calc(-1 * var(--bs-nav-tabs-border-width));background:0 0;border:var(--bs-nav-tabs-border-width) solid transparent;border-top-left-radius:var(--bs-nav-tabs-border-radius);border-top-right-radius:var(--bs-nav-tabs-border-radius)}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{isolation:isolate;border-color:var(--bs-nav-tabs-link-hover-border-color)}.nav-tabs .nav-link.disabled,.nav-tabs .nav-link:disabled{color:var(--bs-nav-link-disabled-color);background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:var(--bs-nav-tabs-link-active-color);background-color:var(--bs-nav-tabs-link-active-bg);border-color:var(--bs-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1 * var(--bs-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--bs-nav-pills-border-radius:0.375rem;--bs-nav-pills-link-active-color:#fff;--bs-nav-pills-link-active-bg:#0d6efd}.nav-pills .nav-link{background:0 0;border:0;border-radius:var(--bs-nav-pills-border-radius)}.nav-pills .nav-link:disabled{color:var(--bs-nav-link-disabled-color);background-color:transparent;border-color:transparent}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--bs-nav-pills-link-active-color);background-color:var(--bs-nav-pills-link-active-bg)}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x:0;--bs-navbar-padding-y:0.5rem;--bs-navbar-color:rgba(0, 0, 0, 0.55);--bs-navbar-hover-color:rgba(0, 0, 0, 0.7);--bs-navbar-disabled-color:rgba(0, 0, 0, 0.3);--bs-navbar-active-color:rgba(0, 0, 0, 0.9);--bs-navbar-brand-padding-y:0.3125rem;--bs-navbar-brand-margin-end:1rem;--bs-navbar-brand-font-size:1.25rem;--bs-navbar-brand-color:rgba(0, 0, 0, 0.9);--bs-navbar-brand-hover-color:rgba(0, 0, 0, 0.9);--bs-navbar-nav-link-padding-x:0.5rem;--bs-navbar-toggler-padding-y:0.25rem;--bs-navbar-toggler-padding-x:0.75rem;--bs-navbar-toggler-font-size:1.25rem;--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--bs-navbar-toggler-border-color:rgba(0, 0, 0, 0.1);--bs-navbar-toggler-border-radius:0.375rem;--bs-navbar-toggler-focus-width:0.25rem;--bs-navbar-toggler-transition:box-shadow 0.15s ease-in-out;position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:var(--bs-navbar-padding-y) var(--bs-navbar-padding-x)}.navbar>.container,.navbar>.container-fluid,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:var(--bs-navbar-brand-padding-y);padding-bottom:var(--bs-navbar-brand-padding-y);margin-right:var(--bs-navbar-brand-margin-end);font-size:var(--bs-navbar-brand-font-size);color:var(--bs-navbar-brand-color);text-decoration:none;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x:0;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-navbar-color);--bs-nav-link-hover-color:var(--bs-navbar-hover-color);--bs-nav-link-disabled-color:var(--bs-navbar-disabled-color);display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link.active,.navbar-nav .show>.nav-link{color:var(--bs-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-navbar-color)}.navbar-text a,.navbar-text a:focus,.navbar-text a:hover{color:var(--bs-navbar-active-color)}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);font-size:var(--bs-navbar-toggler-font-size);line-height:1;color:var(--bs-navbar-color);background-color:transparent;border:var(--bs-border-width) solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);transition:var(--bs-navbar-toggler-transition)}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--bs-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height,75vh);overflow-y:auto}@media (min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-sm .offcanvas .offcanvas-header{display:none}.navbar-expand-sm .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-md .offcanvas .offcanvas-header{display:none}.navbar-expand-md .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-xl .offcanvas .offcanvas-header{display:none}.navbar-expand-xl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-xxl .offcanvas .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand .offcanvas .offcanvas-header{display:none}.navbar-expand .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}.navbar-dark{--bs-navbar-color:rgba(255, 255, 255, 0.55);--bs-navbar-hover-color:rgba(255, 255, 255, 0.75);--bs-navbar-disabled-color:rgba(255, 255, 255, 0.25);--bs-navbar-active-color:#fff;--bs-navbar-brand-color:#fff;--bs-navbar-brand-hover-color:#fff;--bs-navbar-toggler-border-color:rgba(255, 255, 255, 0.1);--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--bs-card-spacer-y:1rem;--bs-card-spacer-x:1rem;--bs-card-title-spacer-y:0.5rem;--bs-card-border-width:1px;--bs-card-border-color:var(--bs-border-color-translucent);--bs-card-border-radius:0.375rem;--bs-card-box-shadow: ;--bs-card-inner-border-radius:calc(0.375rem - 1px);--bs-card-cap-padding-y:0.5rem;--bs-card-cap-padding-x:1rem;--bs-card-cap-bg:rgba(0, 0, 0, 0.03);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg:#fff;--bs-card-img-overlay-padding:1rem;--bs-card-group-margin:0.75rem;position:relative;display:flex;flex-direction:column;min-width:0;height:var(--bs-card-height);word-wrap:break-word;background-color:var(--bs-card-bg);background-clip:border-box;border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius)}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x);color:var(--bs-card-color)}.card-title{margin-bottom:var(--bs-card-title-spacer-y)}.card-subtitle{margin-top:calc(-.5 * var(--bs-card-title-spacer-y));margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:var(--bs-card-spacer-x)}.card-header{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);margin-bottom:0;color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-bottom:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-header:first-child{border-radius:var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0}.card-footer{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-top:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-footer:last-child{border-radius:0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius)}.card-header-tabs{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-bottom:calc(-1 * var(--bs-card-cap-padding-y));margin-left:calc(-.5 * var(--bs-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active{background-color:var(--bs-card-bg);border-bottom-color:var(--bs-card-bg)}.card-header-pills{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-left:calc(-.5 * var(--bs-card-cap-padding-x))}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:var(--bs-card-img-overlay-padding);border-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom,.card-img-top{width:100%}.card-img,.card-img-top{border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom{border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card-group>.card{margin-bottom:var(--bs-card-group-margin)}@media (min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.accordion{--bs-accordion-color:#212529;--bs-accordion-bg:#fff;--bs-accordion-transition:color 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out,border-radius 0.15s ease;--bs-accordion-border-color:var(--bs-border-color);--bs-accordion-border-width:1px;--bs-accordion-border-radius:0.375rem;--bs-accordion-inner-border-radius:calc(0.375rem - 1px);--bs-accordion-btn-padding-x:1.25rem;--bs-accordion-btn-padding-y:1rem;--bs-accordion-btn-color:#212529;--bs-accordion-btn-bg:var(--bs-accordion-bg);--bs-accordion-btn-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-icon-width:1.25rem;--bs-accordion-btn-icon-transform:rotate(-180deg);--bs-accordion-btn-icon-transition:transform 0.2s ease-in-out;--bs-accordion-btn-active-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-focus-border-color:#86b7fe;--bs-accordion-btn-focus-box-shadow:0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-accordion-body-padding-x:1.25rem;--bs-accordion-body-padding-y:1rem;--bs-accordion-active-color:#0c63e4;--bs-accordion-active-bg:#e7f1ff}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x);font-size:1rem;color:var(--bs-accordion-btn-color);text-align:left;background-color:var(--bs-accordion-btn-bg);border:0;border-radius:0;overflow-anchor:none;transition:var(--bs-accordion-transition)}@media (prefers-reduced-motion:reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:var(--bs-accordion-active-color);background-color:var(--bs-accordion-active-bg);box-shadow:inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color)}.accordion-button:not(.collapsed)::after{background-image:var(--bs-accordion-btn-active-icon);transform:var(--bs-accordion-btn-icon-transform)}.accordion-button::after{flex-shrink:0;width:var(--bs-accordion-btn-icon-width);height:var(--bs-accordion-btn-icon-width);margin-left:auto;content:"";background-image:var(--bs-accordion-btn-icon);background-repeat:no-repeat;background-size:var(--bs-accordion-btn-icon-width);transition:var(--bs-accordion-btn-icon-transition)}@media (prefers-reduced-motion:reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:var(--bs-accordion-btn-focus-border-color);outline:0;box-shadow:var(--bs-accordion-btn-focus-box-shadow)}.accordion-header{margin-bottom:0}.accordion-item{color:var(--bs-accordion-color);background-color:var(--bs-accordion-bg);border:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.accordion-item:first-of-type{border-top-left-radius:var(--bs-accordion-border-radius);border-top-right-radius:var(--bs-accordion-border-radius)}.accordion-item:first-of-type .accordion-button{border-top-left-radius:var(--bs-accordion-inner-border-radius);border-top-right-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-right-radius:var(--bs-accordion-inner-border-radius);border-bottom-left-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:last-of-type .accordion-collapse{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-body{padding:var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x)}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.accordion-flush .accordion-item .accordion-button,.accordion-flush .accordion-item .accordion-button.collapsed{border-radius:0}.breadcrumb{--bs-breadcrumb-padding-x:0;--bs-breadcrumb-padding-y:0;--bs-breadcrumb-margin-bottom:1rem;--bs-breadcrumb-bg: ;--bs-breadcrumb-border-radius: ;--bs-breadcrumb-divider-color:#6c757d;--bs-breadcrumb-item-padding-x:0.5rem;--bs-breadcrumb-item-active-color:#6c757d;display:flex;flex-wrap:wrap;padding:var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x);margin-bottom:var(--bs-breadcrumb-margin-bottom);font-size:var(--bs-breadcrumb-font-size);list-style:none;background-color:var(--bs-breadcrumb-bg);border-radius:var(--bs-breadcrumb-border-radius)}.breadcrumb-item+.breadcrumb-item{padding-left:var(--bs-breadcrumb-item-padding-x)}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:var(--bs-breadcrumb-item-padding-x);color:var(--bs-breadcrumb-divider-color);content:var(--bs-breadcrumb-divider, "/")}.breadcrumb-item.active{color:var(--bs-breadcrumb-item-active-color)}.pagination{--bs-pagination-padding-x:0.75rem;--bs-pagination-padding-y:0.375rem;--bs-pagination-font-size:1rem;--bs-pagination-color:var(--bs-link-color);--bs-pagination-bg:#fff;--bs-pagination-border-width:1px;--bs-pagination-border-color:#dee2e6;--bs-pagination-border-radius:0.375rem;--bs-pagination-hover-color:var(--bs-link-hover-color);--bs-pagination-hover-bg:#e9ecef;--bs-pagination-hover-border-color:#dee2e6;--bs-pagination-focus-color:var(--bs-link-hover-color);--bs-pagination-focus-bg:#e9ecef;--bs-pagination-focus-box-shadow:0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-pagination-active-color:#fff;--bs-pagination-active-bg:#0d6efd;--bs-pagination-active-border-color:#0d6efd;--bs-pagination-disabled-color:#6c757d;--bs-pagination-disabled-bg:#fff;--bs-pagination-disabled-border-color:#dee2e6;display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;padding:var(--bs-pagination-padding-y) var(--bs-pagination-padding-x);font-size:var(--bs-pagination-font-size);color:var(--bs-pagination-color);text-decoration:none;background-color:var(--bs-pagination-bg);border:var(--bs-pagination-border-width) solid var(--bs-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--bs-pagination-hover-color);background-color:var(--bs-pagination-hover-bg);border-color:var(--bs-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--bs-pagination-focus-color);background-color:var(--bs-pagination-focus-bg);outline:0;box-shadow:var(--bs-pagination-focus-box-shadow)}.active>.page-link,.page-link.active{z-index:3;color:var(--bs-pagination-active-color);background-color:var(--bs-pagination-active-bg);border-color:var(--bs-pagination-active-border-color)}.disabled>.page-link,.page-link.disabled{color:var(--bs-pagination-disabled-color);pointer-events:none;background-color:var(--bs-pagination-disabled-bg);border-color:var(--bs-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item:first-child .page-link{border-top-left-radius:var(--bs-pagination-border-radius);border-bottom-left-radius:var(--bs-pagination-border-radius)}.page-item:last-child .page-link{border-top-right-radius:var(--bs-pagination-border-radius);border-bottom-right-radius:var(--bs-pagination-border-radius)}.pagination-lg{--bs-pagination-padding-x:1.5rem;--bs-pagination-padding-y:0.75rem;--bs-pagination-font-size:1.25rem;--bs-pagination-border-radius:0.5rem}.pagination-sm{--bs-pagination-padding-x:0.5rem;--bs-pagination-padding-y:0.25rem;--bs-pagination-font-size:0.875rem;--bs-pagination-border-radius:0.25rem}.badge{--bs-badge-padding-x:0.65em;--bs-badge-padding-y:0.35em;--bs-badge-font-size:0.75em;--bs-badge-font-weight:700;--bs-badge-color:#fff;--bs-badge-border-radius:0.375rem;display:inline-block;padding:var(--bs-badge-padding-y) var(--bs-badge-padding-x);font-size:var(--bs-badge-font-size);font-weight:var(--bs-badge-font-weight);line-height:1;color:var(--bs-badge-color);text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:var(--bs-badge-border-radius)}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{--bs-alert-bg:transparent;--bs-alert-padding-x:1rem;--bs-alert-padding-y:1rem;--bs-alert-margin-bottom:1rem;--bs-alert-color:inherit;--bs-alert-border-color:transparent;--bs-alert-border:1px solid var(--bs-alert-border-color);--bs-alert-border-radius:0.375rem;position:relative;padding:var(--bs-alert-padding-y) var(--bs-alert-padding-x);margin-bottom:var(--bs-alert-margin-bottom);color:var(--bs-alert-color);background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius)}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-primary{--bs-alert-color:#084298;--bs-alert-bg:#cfe2ff;--bs-alert-border-color:#b6d4fe}.alert-primary .alert-link{color:#06357a}.alert-secondary{--bs-alert-color:#41464b;--bs-alert-bg:#e2e3e5;--bs-alert-border-color:#d3d6d8}.alert-secondary .alert-link{color:#34383c}.alert-success{--bs-alert-color:#0f5132;--bs-alert-bg:#d1e7dd;--bs-alert-border-color:#badbcc}.alert-success .alert-link{color:#0c4128}.alert-info{--bs-alert-color:#055160;--bs-alert-bg:#cff4fc;--bs-alert-border-color:#b6effb}.alert-info .alert-link{color:#04414d}.alert-warning{--bs-alert-color:#664d03;--bs-alert-bg:#fff3cd;--bs-alert-border-color:#ffecb5}.alert-warning .alert-link{color:#523e02}.alert-danger{--bs-alert-color:#842029;--bs-alert-bg:#f8d7da;--bs-alert-border-color:#f5c2c7}.alert-danger .alert-link{color:#6a1a21}.alert-light{--bs-alert-color:#636464;--bs-alert-bg:#fefefe;--bs-alert-border-color:#fdfdfe}.alert-light .alert-link{color:#4f5050}.alert-dark{--bs-alert-color:#141619;--bs-alert-bg:#d3d3d4;--bs-alert-border-color:#bcbebf}.alert-dark .alert-link{color:#101214}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress{--bs-progress-height:1rem;--bs-progress-font-size:0.75rem;--bs-progress-bg:#e9ecef;--bs-progress-border-radius:0.375rem;--bs-progress-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-progress-bar-color:#fff;--bs-progress-bar-bg:#0d6efd;--bs-progress-bar-transition:width 0.6s ease;display:flex;height:var(--bs-progress-height);overflow:hidden;font-size:var(--bs-progress-font-size);background-color:var(--bs-progress-bg);border-radius:var(--bs-progress-border-radius)}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:var(--bs-progress-bar-color);text-align:center;white-space:nowrap;background-color:var(--bs-progress-bar-bg);transition:var(--bs-progress-bar-transition)}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:var(--bs-progress-height) var(--bs-progress-height)}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.list-group{--bs-list-group-color:#212529;--bs-list-group-bg:#fff;--bs-list-group-border-color:rgba(0, 0, 0, 0.125);--bs-list-group-border-width:1px;--bs-list-group-border-radius:0.375rem;--bs-list-group-item-padding-x:1rem;--bs-list-group-item-padding-y:0.5rem;--bs-list-group-action-color:#495057;--bs-list-group-action-hover-color:#495057;--bs-list-group-action-hover-bg:#f8f9fa;--bs-list-group-action-active-color:#212529;--bs-list-group-action-active-bg:#e9ecef;--bs-list-group-disabled-color:#6c757d;--bs-list-group-disabled-bg:#fff;--bs-list-group-active-color:#fff;--bs-list-group-active-bg:#0d6efd;--bs-list-group-active-border-color:#0d6efd;display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:var(--bs-list-group-border-radius)}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>.list-group-item::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item-action{width:100%;color:var(--bs-list-group-action-color);text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:var(--bs-list-group-action-hover-color);text-decoration:none;background-color:var(--bs-list-group-action-hover-bg)}.list-group-item-action:active{color:var(--bs-list-group-action-active-color);background-color:var(--bs-list-group-action-active-bg)}.list-group-item{position:relative;display:block;padding:var(--bs-list-group-item-padding-y) var(--bs-list-group-item-padding-x);color:var(--bs-list-group-color);text-decoration:none;background-color:var(--bs-list-group-bg);border:var(--bs-list-group-border-width) solid var(--bs-list-group-border-color)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:var(--bs-list-group-disabled-color);pointer-events:none;background-color:var(--bs-list-group-disabled-bg)}.list-group-item.active{z-index:2;color:var(--bs-list-group-active-color);background-color:var(--bs-list-group-active-bg);border-color:var(--bs-list-group-active-border-color)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:calc(-1 * var(--bs-list-group-border-width));border-top-width:var(--bs-list-group-border-width)}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}@media (min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 var(--bs-list-group-border-width)}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#084298;background-color:#cfe2ff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#084298;background-color:#bacbe6}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#084298;border-color:#084298}.list-group-item-secondary{color:#41464b;background-color:#e2e3e5}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#41464b;background-color:#cbccce}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#41464b;border-color:#41464b}.list-group-item-success{color:#0f5132;background-color:#d1e7dd}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#0f5132;background-color:#bcd0c7}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#0f5132;border-color:#0f5132}.list-group-item-info{color:#055160;background-color:#cff4fc}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#055160;background-color:#badce3}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#055160;border-color:#055160}.list-group-item-warning{color:#664d03;background-color:#fff3cd}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#664d03;background-color:#e6dbb9}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#664d03;border-color:#664d03}.list-group-item-danger{color:#842029;background-color:#f8d7da}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#842029;background-color:#dfc2c4}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#842029;border-color:#842029}.list-group-item-light{color:#636464;background-color:#fefefe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#636464;background-color:#e5e5e5}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#636464;border-color:#636464}.list-group-item-dark{color:#141619;background-color:#d3d3d4}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#141619;background-color:#bebebf}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#141619;border-color:#141619}.btn-close{box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:#000;background:transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat;border:0;border-radius:.375rem;opacity:.5}.btn-close:hover{color:#000;text-decoration:none;opacity:.75}.btn-close:focus{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);opacity:1}.btn-close.disabled,.btn-close:disabled{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;opacity:.25}.btn-close-white{filter:invert(1) grayscale(100%) brightness(200%)}.toast{--bs-toast-zindex:1090;--bs-toast-padding-x:0.75rem;--bs-toast-padding-y:0.5rem;--bs-toast-spacing:1.5rem;--bs-toast-max-width:350px;--bs-toast-font-size:0.875rem;--bs-toast-color: ;--bs-toast-bg:rgba(255, 255, 255, 0.85);--bs-toast-border-width:1px;--bs-toast-border-color:var(--bs-border-color-translucent);--bs-toast-border-radius:0.375rem;--bs-toast-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-toast-header-color:#6c757d;--bs-toast-header-bg:rgba(255, 255, 255, 0.85);--bs-toast-header-border-color:rgba(0, 0, 0, 0.05);width:var(--bs-toast-max-width);max-width:100%;font-size:var(--bs-toast-font-size);color:var(--bs-toast-color);pointer-events:auto;background-color:var(--bs-toast-bg);background-clip:padding-box;border:var(--bs-toast-border-width) solid var(--bs-toast-border-color);box-shadow:var(--bs-toast-box-shadow);border-radius:var(--bs-toast-border-radius)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--bs-toast-zindex:1090;position:absolute;z-index:var(--bs-toast-zindex);width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--bs-toast-spacing)}.toast-header{display:flex;align-items:center;padding:var(--bs-toast-padding-y) var(--bs-toast-padding-x);color:var(--bs-toast-header-color);background-color:var(--bs-toast-header-bg);background-clip:padding-box;border-bottom:var(--bs-toast-border-width) solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width))}.toast-header .btn-close{margin-right:calc(-.5 * var(--bs-toast-padding-x));margin-left:var(--bs-toast-padding-x)}.toast-body{padding:var(--bs-toast-padding-x);word-wrap:break-word}.modal{--bs-modal-zindex:1055;--bs-modal-width:500px;--bs-modal-padding:1rem;--bs-modal-margin:0.5rem;--bs-modal-color: ;--bs-modal-bg:#fff;--bs-modal-border-color:var(--bs-border-color-translucent);--bs-modal-border-width:1px;--bs-modal-border-radius:0.5rem;--bs-modal-box-shadow:0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-modal-inner-border-radius:calc(0.5rem - 1px);--bs-modal-header-padding-x:1rem;--bs-modal-header-padding-y:1rem;--bs-modal-header-padding:1rem 1rem;--bs-modal-header-border-color:var(--bs-border-color);--bs-modal-header-border-width:1px;--bs-modal-title-line-height:1.5;--bs-modal-footer-gap:0.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color:var(--bs-border-color);--bs-modal-footer-border-width:1px;position:fixed;top:0;left:0;z-index:var(--bs-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--bs-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--bs-modal-margin) * 2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - var(--bs-modal-margin) * 2)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--bs-modal-color);pointer-events:auto;background-color:var(--bs-modal-bg);background-clip:padding-box;border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);outline:0}.modal-backdrop{--bs-backdrop-zindex:1050;--bs-backdrop-bg:#000;--bs-backdrop-opacity:0.5;position:fixed;top:0;left:0;z-index:var(--bs-backdrop-zindex);width:100vw;height:100vh;background-color:var(--bs-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--bs-backdrop-opacity)}.modal-header{display:flex;flex-shrink:0;align-items:center;justify-content:space-between;padding:var(--bs-modal-header-padding);border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--bs-modal-header-padding-y) * .5) calc(var(--bs-modal-header-padding-x) * .5);margin:calc(-.5 * var(--bs-modal-header-padding-y)) calc(-.5 * var(--bs-modal-header-padding-x)) calc(-.5 * var(--bs-modal-header-padding-y)) auto}.modal-title{margin-bottom:0;line-height:var(--bs-modal-title-line-height)}.modal-body{position:relative;flex:1 1 auto;padding:var(--bs-modal-padding)}.modal-footer{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * .5);background-color:var(--bs-modal-footer-bg);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-bottom-left-radius:var(--bs-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap) * .5)}@media (min-width:576px){.modal{--bs-modal-margin:1.75rem;--bs-modal-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15)}.modal-dialog{max-width:var(--bs-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--bs-modal-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{--bs-modal-width:800px}}@media (min-width:1200px){.modal-xl{--bs-modal-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-footer,.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media (max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-footer,.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media (max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-footer,.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media (max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-footer,.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media (max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-footer,.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media (max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-footer,.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--bs-tooltip-zindex:1080;--bs-tooltip-max-width:200px;--bs-tooltip-padding-x:0.5rem;--bs-tooltip-padding-y:0.25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:0.875rem;--bs-tooltip-color:#fff;--bs-tooltip-bg:#000;--bs-tooltip-border-radius:0.375rem;--bs-tooltip-opacity:0.9;--bs-tooltip-arrow-width:0.8rem;--bs-tooltip-arrow-height:0.4rem;z-index:var(--bs-tooltip-zindex);display:block;padding:var(--bs-tooltip-arrow-height);margin:var(--bs-tooltip-margin);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-tooltip-font-size);word-wrap:break-word;opacity:0}.tooltip.show{opacity:var(--bs-tooltip-opacity)}.tooltip .tooltip-arrow{display:block;width:var(--bs-tooltip-arrow-width);height:var(--bs-tooltip-arrow-height)}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow,.bs-tooltip-top .tooltip-arrow{bottom:0}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before,.bs-tooltip-top .tooltip-arrow::before{top:-1px;border-width:var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-top-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow,.bs-tooltip-end .tooltip-arrow{left:0;width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before,.bs-tooltip-end .tooltip-arrow::before{right:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-right-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow,.bs-tooltip-bottom .tooltip-arrow{top:0}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before,.bs-tooltip-bottom .tooltip-arrow::before{bottom:-1px;border-width:0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-bottom-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow,.bs-tooltip-start .tooltip-arrow{right:0;width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before,.bs-tooltip-start .tooltip-arrow::before{left:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) 0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-left-color:var(--bs-tooltip-bg)}.tooltip-inner{max-width:var(--bs-tooltip-max-width);padding:var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x);color:var(--bs-tooltip-color);text-align:center;background-color:var(--bs-tooltip-bg);border-radius:var(--bs-tooltip-border-radius)}.popover{--bs-popover-zindex:1070;--bs-popover-max-width:276px;--bs-popover-font-size:0.875rem;--bs-popover-bg:#fff;--bs-popover-border-width:1px;--bs-popover-border-color:var(--bs-border-color-translucent);--bs-popover-border-radius:0.5rem;--bs-popover-inner-border-radius:calc(0.5rem - 1px);--bs-popover-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-popover-header-padding-x:1rem;--bs-popover-header-padding-y:0.5rem;--bs-popover-header-font-size:1rem;--bs-popover-header-color: ;--bs-popover-header-bg:#f0f0f0;--bs-popover-body-padding-x:1rem;--bs-popover-body-padding-y:1rem;--bs-popover-body-color:#212529;--bs-popover-arrow-width:1rem;--bs-popover-arrow-height:0.5rem;--bs-popover-arrow-border:var(--bs-popover-border-color);z-index:var(--bs-popover-zindex);display:block;max-width:var(--bs-popover-max-width);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-popover-font-size);word-wrap:break-word;background-color:var(--bs-popover-bg);background-clip:padding-box;border:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-radius:var(--bs-popover-border-radius)}.popover .popover-arrow{display:block;width:var(--bs-popover-arrow-width);height:var(--bs-popover-arrow-height)}.popover .popover-arrow::after,.popover .popover-arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid;border-width:0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow,.bs-popover-top>.popover-arrow{bottom:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::after,.bs-popover-top>.popover-arrow::before{border-width:var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::before{bottom:0;border-top-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-top>.popover-arrow::after{bottom:var(--bs-popover-border-width);border-top-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow,.bs-popover-end>.popover-arrow{left:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::after,.bs-popover-end>.popover-arrow::before{border-width:calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::before{left:0;border-right-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-end>.popover-arrow::after{left:var(--bs-popover-border-width);border-right-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow,.bs-popover-bottom>.popover-arrow{top:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::before{border-width:0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::before{top:0;border-bottom-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::after{top:var(--bs-popover-border-width);border-bottom-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:var(--bs-popover-arrow-width);margin-left:calc(-.5 * var(--bs-popover-arrow-width));content:"";border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-header-bg)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow,.bs-popover-start>.popover-arrow{right:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::after,.bs-popover-start>.popover-arrow::before{border-width:calc(var(--bs-popover-arrow-width) * .5) 0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::before{right:0;border-left-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-start>.popover-arrow::after{right:var(--bs-popover-border-width);border-left-color:var(--bs-popover-bg)}.popover-header{padding:var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x);margin-bottom:0;font-size:var(--bs-popover-header-font-size);color:var(--bs-popover-header-color);background-color:var(--bs-popover-header-bg);border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-top-left-radius:var(--bs-popover-inner-border-radius);border-top-right-radius:var(--bs-popover-inner-border-radius)}.popover-header:empty{display:none}.popover-body{padding:var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x);color:var(--bs-popover-body-color)}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-end,.carousel-item-next:not(.carousel-item-start){transform:translateX(100%)}.active.carousel-item-start,.carousel-item-prev:not(.carousel-item-end){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%;list-style:none}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-next-icon,.carousel-dark .carousel-control-prev-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}.spinner-border,.spinner-grow{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-border-width:0.25em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-border;border:var(--bs-spinner-border-width) solid currentcolor;border-right-color:transparent}.spinner-border-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem;--bs-spinner-border-width:0.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-grow;background-color:currentcolor;opacity:0}.spinner-grow-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{--bs-spinner-animation-speed:1.5s}}.offcanvas,.offcanvas-lg,.offcanvas-md,.offcanvas-sm,.offcanvas-xl,.offcanvas-xxl{--bs-offcanvas-zindex:1045;--bs-offcanvas-width:400px;--bs-offcanvas-height:30vh;--bs-offcanvas-padding-x:1rem;--bs-offcanvas-padding-y:1rem;--bs-offcanvas-color: ;--bs-offcanvas-bg:#fff;--bs-offcanvas-border-width:1px;--bs-offcanvas-border-color:var(--bs-border-color-translucent);--bs-offcanvas-box-shadow:0 0.125rem 0.25rem rgba(0, 0, 0, 0.075)}@media (max-width:575.98px){.offcanvas-sm{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}}@media (max-width:575.98px) and (prefers-reduced-motion:reduce){.offcanvas-sm{transition:none}}@media (max-width:575.98px){.offcanvas-sm.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}}@media (max-width:575.98px){.offcanvas-sm.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}}@media (max-width:575.98px){.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}}@media (max-width:575.98px){.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}}@media (max-width:575.98px){.offcanvas-sm.show:not(.hiding),.offcanvas-sm.showing{transform:none}}@media (max-width:575.98px){.offcanvas-sm.hiding,.offcanvas-sm.show,.offcanvas-sm.showing{visibility:visible}}@media (min-width:576px){.offcanvas-sm{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:767.98px){.offcanvas-md{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}}@media (max-width:767.98px) and (prefers-reduced-motion:reduce){.offcanvas-md{transition:none}}@media (max-width:767.98px){.offcanvas-md.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}}@media (max-width:767.98px){.offcanvas-md.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}}@media (max-width:767.98px){.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}}@media (max-width:767.98px){.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}}@media (max-width:767.98px){.offcanvas-md.show:not(.hiding),.offcanvas-md.showing{transform:none}}@media (max-width:767.98px){.offcanvas-md.hiding,.offcanvas-md.show,.offcanvas-md.showing{visibility:visible}}@media (min-width:768px){.offcanvas-md{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:991.98px){.offcanvas-lg{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}}@media (max-width:991.98px) and (prefers-reduced-motion:reduce){.offcanvas-lg{transition:none}}@media (max-width:991.98px){.offcanvas-lg.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}}@media (max-width:991.98px){.offcanvas-lg.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}}@media (max-width:991.98px){.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}}@media (max-width:991.98px){.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}}@media (max-width:991.98px){.offcanvas-lg.show:not(.hiding),.offcanvas-lg.showing{transform:none}}@media (max-width:991.98px){.offcanvas-lg.hiding,.offcanvas-lg.show,.offcanvas-lg.showing{visibility:visible}}@media (min-width:992px){.offcanvas-lg{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1199.98px){.offcanvas-xl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}}@media (max-width:1199.98px) and (prefers-reduced-motion:reduce){.offcanvas-xl{transition:none}}@media (max-width:1199.98px){.offcanvas-xl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}}@media (max-width:1199.98px){.offcanvas-xl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}}@media (max-width:1199.98px){.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}}@media (max-width:1199.98px){.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}}@media (max-width:1199.98px){.offcanvas-xl.show:not(.hiding),.offcanvas-xl.showing{transform:none}}@media (max-width:1199.98px){.offcanvas-xl.hiding,.offcanvas-xl.show,.offcanvas-xl.showing{visibility:visible}}@media (min-width:1200px){.offcanvas-xl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1399.98px){.offcanvas-xxl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}}@media (max-width:1399.98px) and (prefers-reduced-motion:reduce){.offcanvas-xxl{transition:none}}@media (max-width:1399.98px){.offcanvas-xxl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}}@media (max-width:1399.98px){.offcanvas-xxl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}}@media (max-width:1399.98px){.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}}@media (max-width:1399.98px){.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}}@media (max-width:1399.98px){.offcanvas-xxl.show:not(.hiding),.offcanvas-xxl.showing{transform:none}}@media (max-width:1399.98px){.offcanvas-xxl.hiding,.offcanvas-xxl.show,.offcanvas-xxl.showing{visibility:visible}}@media (min-width:1400px){.offcanvas-xxl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}.offcanvas{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}@media (prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas.show:not(.hiding),.offcanvas.showing{transform:none}.offcanvas.hiding,.offcanvas.show,.offcanvas.showing{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;align-items:center;justify-content:space-between;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x)}.offcanvas-header .btn-close{padding:calc(var(--bs-offcanvas-padding-y) * .5) calc(var(--bs-offcanvas-padding-x) * .5);margin-top:calc(-.5 * var(--bs-offcanvas-padding-y));margin-right:calc(-.5 * var(--bs-offcanvas-padding-x));margin-bottom:calc(-.5 * var(--bs-offcanvas-padding-y))}.offcanvas-title{margin-bottom:0;line-height:1.5}.offcanvas-body{flex-grow:1;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);overflow-y:auto}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentcolor;opacity:.5}.placeholder.btn::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{-webkit-mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);-webkit-mask-size:200% 100%;mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{100%{-webkit-mask-position:-200% 0%;mask-position:-200% 0%}}.clearfix::after{display:block;clear:both;content:""}.text-bg-primary{color:#fff!important;background-color:RGBA(13,110,253,var(--bs-bg-opacity,1))!important}.text-bg-secondary{color:#fff!important;background-color:RGBA(108,117,125,var(--bs-bg-opacity,1))!important}.text-bg-success{color:#fff!important;background-color:RGBA(25,135,84,var(--bs-bg-opacity,1))!important}.text-bg-info{color:#000!important;background-color:RGBA(13,202,240,var(--bs-bg-opacity,1))!important}.text-bg-warning{color:#000!important;background-color:RGBA(255,193,7,var(--bs-bg-opacity,1))!important}.text-bg-danger{color:#fff!important;background-color:RGBA(220,53,69,var(--bs-bg-opacity,1))!important}.text-bg-light{color:#000!important;background-color:RGBA(248,249,250,var(--bs-bg-opacity,1))!important}.text-bg-dark{color:#fff!important;background-color:RGBA(33,37,41,var(--bs-bg-opacity,1))!important}.link-primary{color:#0d6efd!important}.link-primary:focus,.link-primary:hover{color:#0a58ca!important}.link-secondary{color:#6c757d!important}.link-secondary:focus,.link-secondary:hover{color:#565e64!important}.link-success{color:#198754!important}.link-success:focus,.link-success:hover{color:#146c43!important}.link-info{color:#0dcaf0!important}.link-info:focus,.link-info:hover{color:#3dd5f3!important}.link-warning{color:#ffc107!important}.link-warning:focus,.link-warning:hover{color:#ffcd39!important}.link-danger{color:#dc3545!important}.link-danger:focus,.link-danger:hover{color:#b02a37!important}.link-light{color:#f8f9fa!important}.link-light:focus,.link-light:hover{color:#f9fafb!important}.link-dark{color:#212529!important}.link-dark:focus,.link-dark:hover{color:#1a1e21!important}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio:100%}.ratio-4x3{--bs-aspect-ratio:75%}.ratio-16x9{--bs-aspect-ratio:56.25%}.ratio-21x9{--bs-aspect-ratio:42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}@media (min-width:576px){.sticky-sm-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:768px){.sticky-md-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:992px){.sticky-lg-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:1200px){.sticky-xl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:1400px){.sticky-xxl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}.hstack{display:flex;flex-direction:row;align-items:center;align-self:stretch}.vstack{display:flex;flex:1 1 auto;flex-direction:column;align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;width:1px;min-height:1em;background-color:currentcolor;opacity:.25}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.opacity-0{opacity:0!important}.opacity-25{opacity:.25!important}.opacity-50{opacity:.5!important}.opacity-75{opacity:.75!important}.opacity-100{opacity:1!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translateX(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-0{border:0!important}.border-top{border-top:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-top-0{border-top:0!important}.border-end{border-right:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-start-0{border-left:0!important}.border-primary{--bs-border-opacity:1;border-color:rgba(var(--bs-primary-rgb),var(--bs-border-opacity))!important}.border-secondary{--bs-border-opacity:1;border-color:rgba(var(--bs-secondary-rgb),var(--bs-border-opacity))!important}.border-success{--bs-border-opacity:1;border-color:rgba(var(--bs-success-rgb),var(--bs-border-opacity))!important}.border-info{--bs-border-opacity:1;border-color:rgba(var(--bs-info-rgb),var(--bs-border-opacity))!important}.border-warning{--bs-border-opacity:1;border-color:rgba(var(--bs-warning-rgb),var(--bs-border-opacity))!important}.border-danger{--bs-border-opacity:1;border-color:rgba(var(--bs-danger-rgb),var(--bs-border-opacity))!important}.border-light{--bs-border-opacity:1;border-color:rgba(var(--bs-light-rgb),var(--bs-border-opacity))!important}.border-dark{--bs-border-opacity:1;border-color:rgba(var(--bs-dark-rgb),var(--bs-border-opacity))!important}.border-white{--bs-border-opacity:1;border-color:rgba(var(--bs-white-rgb),var(--bs-border-opacity))!important}.border-1{--bs-border-width:1px}.border-2{--bs-border-width:2px}.border-3{--bs-border-width:3px}.border-4{--bs-border-width:4px}.border-5{--bs-border-width:5px}.border-opacity-10{--bs-border-opacity:0.1}.border-opacity-25{--bs-border-opacity:0.25}.border-opacity-50{--bs-border-opacity:0.5}.border-opacity-75{--bs-border-opacity:0.75}.border-opacity-100{--bs-border-opacity:1}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:1 1 auto!important}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.justify-content-evenly{justify-content:space-evenly!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:3rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:3rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:3rem!important}.ms-auto{margin-left:auto!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:3rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:3rem!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:3rem!important}.font-monospace{font-family:var(--bs-font-monospace)!important}.fs-1{font-size:calc(1.375rem + 1.5vw)!important}.fs-2{font-size:calc(1.325rem + .9vw)!important}.fs-3{font-size:calc(1.3rem + .6vw)!important}.fs-4{font-size:calc(1.275rem + .3vw)!important}.fs-5{font-size:1.25rem!important}.fs-6{font-size:1rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-light{font-weight:300!important}.fw-lighter{font-weight:lighter!important}.fw-normal{font-weight:400!important}.fw-bold{font-weight:700!important}.fw-semibold{font-weight:600!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.25!important}.lh-base{line-height:1.5!important}.lh-lg{line-height:2!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--bs-text-opacity:1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))!important}.text-secondary{--bs-text-opacity:1;color:rgba(var(--bs-secondary-rgb),var(--bs-text-opacity))!important}.text-success{--bs-text-opacity:1;color:rgba(var(--bs-success-rgb),var(--bs-text-opacity))!important}.text-info{--bs-text-opacity:1;color:rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important}.text-warning{--bs-text-opacity:1;color:rgba(var(--bs-warning-rgb),var(--bs-text-opacity))!important}.text-danger{--bs-text-opacity:1;color:rgba(var(--bs-danger-rgb),var(--bs-text-opacity))!important}.text-light{--bs-text-opacity:1;color:rgba(var(--bs-light-rgb),var(--bs-text-opacity))!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-black{--bs-text-opacity:1;color:rgba(var(--bs-black-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-body{--bs-text-opacity:1;color:rgba(var(--bs-body-color-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity:1;color:#6c757d!important}.text-black-50{--bs-text-opacity:1;color:rgba(0,0,0,.5)!important}.text-white-50{--bs-text-opacity:1;color:rgba(255,255,255,.5)!important}.text-reset{--bs-text-opacity:1;color:inherit!important}.text-opacity-25{--bs-text-opacity:0.25}.text-opacity-50{--bs-text-opacity:0.5}.text-opacity-75{--bs-text-opacity:0.75}.text-opacity-100{--bs-text-opacity:1}.bg-primary{--bs-bg-opacity:1;background-color:rgba(var(--bs-primary-rgb),var(--bs-bg-opacity))!important}.bg-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-rgb),var(--bs-bg-opacity))!important}.bg-success{--bs-bg-opacity:1;background-color:rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important}.bg-info{--bs-bg-opacity:1;background-color:rgba(var(--bs-info-rgb),var(--bs-bg-opacity))!important}.bg-warning{--bs-bg-opacity:1;background-color:rgba(var(--bs-warning-rgb),var(--bs-bg-opacity))!important}.bg-danger{--bs-bg-opacity:1;background-color:rgba(var(--bs-danger-rgb),var(--bs-bg-opacity))!important}.bg-light{--bs-bg-opacity:1;background-color:rgba(var(--bs-light-rgb),var(--bs-bg-opacity))!important}.bg-dark{--bs-bg-opacity:1;background-color:rgba(var(--bs-dark-rgb),var(--bs-bg-opacity))!important}.bg-black{--bs-bg-opacity:1;background-color:rgba(var(--bs-black-rgb),var(--bs-bg-opacity))!important}.bg-white{--bs-bg-opacity:1;background-color:rgba(var(--bs-white-rgb),var(--bs-bg-opacity))!important}.bg-body{--bs-bg-opacity:1;background-color:rgba(var(--bs-body-bg-rgb),var(--bs-bg-opacity))!important}.bg-transparent{--bs-bg-opacity:1;background-color:transparent!important}.bg-opacity-10{--bs-bg-opacity:0.1}.bg-opacity-25{--bs-bg-opacity:0.25}.bg-opacity-50{--bs-bg-opacity:0.5}.bg-opacity-75{--bs-bg-opacity:0.75}.bg-opacity-100{--bs-bg-opacity:1}.bg-gradient{background-image:var(--bs-gradient)!important}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:var(--bs-border-radius)!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:var(--bs-border-radius-sm)!important}.rounded-2{border-radius:var(--bs-border-radius)!important}.rounded-3{border-radius:var(--bs-border-radius-lg)!important}.rounded-4{border-radius:var(--bs-border-radius-xl)!important}.rounded-5{border-radius:var(--bs-border-radius-2xl)!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:var(--bs-border-radius-pill)!important}.rounded-top{border-top-left-radius:var(--bs-border-radius)!important;border-top-right-radius:var(--bs-border-radius)!important}.rounded-end{border-top-right-radius:var(--bs-border-radius)!important;border-bottom-right-radius:var(--bs-border-radius)!important}.rounded-bottom{border-bottom-right-radius:var(--bs-border-radius)!important;border-bottom-left-radius:var(--bs-border-radius)!important}.rounded-start{border-bottom-left-radius:var(--bs-border-radius)!important;border-top-left-radius:var(--bs-border-radius)!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media (min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.justify-content-sm-evenly{justify-content:space-evenly!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:3rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:3rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:3rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:3rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:3rem!important}.ms-sm-auto{margin-left:auto!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:3rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:3rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:3rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:3rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:3rem!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:3rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.justify-content-md-evenly{justify-content:space-evenly!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:3rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:3rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:3rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:3rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:3rem!important}.ms-md-auto{margin-left:auto!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:3rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:3rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:3rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:3rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:3rem!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:3rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.justify-content-lg-evenly{justify-content:space-evenly!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:3rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:3rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:3rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:3rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:3rem!important}.ms-lg-auto{margin-left:auto!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:3rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:3rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:3rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:3rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:3rem!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:3rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.justify-content-xl-evenly{justify-content:space-evenly!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:3rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:3rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:3rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:3rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:3rem!important}.ms-xl-auto{margin-left:auto!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:3rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:3rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:3rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:3rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:3rem!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:3rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}}@media (min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:1 1 auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:3rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:3rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:3rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:3rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:3rem!important}.ms-xxl-auto{margin-left:auto!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:3rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:3rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:3rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:3rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:3rem!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:3rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}}@media (min-width:1200px){.fs-1{font-size:2.5rem!important}.fs-2{font-size:2rem!important}.fs-3{font-size:1.75rem!important}.fs-4{font-size:1.5rem!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/django/Invoice/templates/Invoice/create-update.html b/django/Invoice/templates/Invoice/create-update.html new file mode 100644 index 0000000..ca52c15 --- /dev/null +++ b/django/Invoice/templates/Invoice/create-update.html @@ -0,0 +1,525 @@ +{% extends 'base.html' %} +{% load crispy_forms_tags %} +{% load humanize %} +{% block title %}Invoice{% endblock title %} + +{% block body %} + {% comment %} {% if messages %} + + {% endif %} {% endcomment %} + {% if messages %} +
    + {% for message in messages %} + {{ message }} + {% endfor %} +
+ {% endif %} + +
+
+ {% csrf_token %} +
+
{{form.CustomerRefFullName|as_crispy_field}}
+
+
+
{{form.BillAddr1|as_crispy_field}}
+
+
+
{{form.TxnDate|as_crispy_field}}
+
{{form.RefNumber|as_crispy_field}}
+
+
+ +
{{form.PONumber|as_crispy_field}}
+
+
+
{{form.SalesRepRefFullName|as_crispy_field}}
+
+ +
+
{{form.ShipAddr1|as_crispy_field}}
+
+ {{form.TotalAmount}} + + {% comment %}
{{form.IsToBePrinted.as_hidden}}
+
{{form.IsToBeEmailed.as_hidden}}
+
{{form.IsManuallyClosed.as_hidden}}
{% endcomment %} +
{{form.KTP.as_hidden}}
+
{{form.NPWP.as_hidden}}
+
{{form.DMS_Cust_Name.as_hidden}}
+
{{form.DMS_Cust_Code.as_hidden}}
+
{{form.Special_Cust.as_hidden}}
+
{{form.EFaktur_Name.as_hidden}}
+
{{form.Efaktur_Address.as_hidden}}
+
{{form.Coordinates.as_hidden}}
+
+ + + {% for hidden in form.hidden_fields %} + {{ hidden }} + {% endfor %} + + {% if formset %} + {{ formset.management_form }} +
+
ItemRefFullName*
+
Description
+
Qty
+
UOM
+
Rate
+
+
+
+ Amount
+
Del
+
+
+ +
+ {% comment %} {% for form in formset %} {% endcomment %} + {% for qs, form in qsformset %} +
+ {{form.id}} + {% comment %} {{form.ItemRefFullName.field}} {% endcomment %} +
+
+
+ {% comment %} {% endcomment %} +
+ +
+
+ +
{{form.Desc|as_crispy_field}}
+
{{form.Quantity|as_crispy_field}}
+
{{form.UnitOfMeasure|as_crispy_field}}
+
{{form.Rate|as_crispy_field}}
+ +
+
+
{{form.Amount|as_crispy_field}}
+
{{form.DELETE|as_crispy_field}}
+
+
+ {{form.Invoiced.as_hidden}} + {{form.LineIsManuallyClosed.as_hidden}} +
+
+ {% endfor %} +
+
+ + {% endif %} +
+
+ + + + {% comment %}
{% endcomment %} +
+
+ Total Amount Rp. +
+
{{form.TotalAmount.value|intcomma}} + + {% comment %} {% endcomment %} +
+ {% comment %}
{% endcomment %} +
+
+ + + +
+ + {% for item in itemdatalist %} + + + + + + + +{% endblock body %} \ No newline at end of file diff --git a/django/Invoice/templates/Invoice/home.html b/django/Invoice/templates/Invoice/home.html new file mode 100644 index 0000000..1f84523 --- /dev/null +++ b/django/Invoice/templates/Invoice/home.html @@ -0,0 +1,8 @@ +{% extends 'base.html'%} +{% block body %} +
+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} \ No newline at end of file diff --git a/django/Invoice/templates/Invoice/index_invoice.html b/django/Invoice/templates/Invoice/index_invoice.html new file mode 100644 index 0000000..4a3e7c0 --- /dev/null +++ b/django/Invoice/templates/Invoice/index_invoice.html @@ -0,0 +1 @@ +{% include 'Item/table_index.html' with title="Invoice Order Index" %} \ No newline at end of file diff --git a/django/Invoice/templates/Invoice/show-customers.html b/django/Invoice/templates/Invoice/show-customers.html new file mode 100644 index 0000000..62379c1 --- /dev/null +++ b/django/Invoice/templates/Invoice/show-customers.html @@ -0,0 +1,406 @@ +{% extends 'base.html' %} +{% load crispy_forms_tags %} +{% load humanize %} +{% block title %}Invoice{% endblock title %} + +{% block body %} + {% comment %} {% if messages %} + + {% endif %} {% endcomment %} + {% if messages %} +
    + {% for message in messages %} + {{ message }} + {% endfor %} +
+ {% endif %} + +
+
+ {% csrf_token %} +
+
+ + + + + +
+
+ + + {% for customer in customers %} + + + + + + +{% endblock body %} \ 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 new file mode 100644 index 0000000..2b6137a --- /dev/null +++ b/django/Invoice/templates/Invoice/so_list_form.html @@ -0,0 +1,47 @@ +{% extends 'base.html' %} +{% block body %} + +
+ +
+{% endblock %} \ No newline at end of file diff --git a/django/Invoice/templates/Invoice/temp.html b/django/Invoice/templates/Invoice/temp.html new file mode 100644 index 0000000..098506f --- /dev/null +++ b/django/Invoice/templates/Invoice/temp.html @@ -0,0 +1,105 @@ +{% comment %} {{form.CustomerRefFullName.errors}} + + {% if form.non_field_errors %} +
    + {% for error in form.non_field_errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %} + + {% for hidden_field in form.hidden_fields %} + {% if hidden_field.errors %} +
    + {% for error in hidden_field.errors %} +
  • (Hidden field {{ hidden_field.name }}) {{ error }}
  • + {% endfor %} +
+ {% endif %} + {{ hidden_field }} + {% endfor %} + + + {% for field in form.visible_fields %} + + + + + {% endfor %} +
{{ field.label_tag }} + {% if field.errors %} +
    + {% for error in field.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %} + {{ field }} + {% if field.help_text %} +
{{ field.help_text }} + {% endif %} +
{% endcomment %} + + + +{% comment %}
+
+
+
+
+ I'm the first element in the nested grid +
+
+ I'm the second element in the nested grid +
+
+
+
+ I'm the second element in the first grid +
+
+ I'm the third element in the first grid +
+
+
+ +
+ +
+
{{form.CustomerRefFullName|as_crispy_field}}
+ +
+
{{form.BillAddr1|as_crispy_field}}
+
+
+
{{form.TxnDate|as_crispy_field}}
+
{{form.RefNumber|as_crispy_field}}
+
+
+
{{form.CustomerRefFullName|as_crispy_field}}
+
{{form.BillAddr3|as_crispy_field}}
+
{{form.RefNumber|as_crispy_field}}
+
+
+
Outer row 1, column 3 - spans two rows (column 2 has two rows)
+
+
+ +
+
+
{{form.BillAddr1|as_crispy_field}}
+
+
+
{{form.CustomerRefFullName|as_crispy_field}}
+
{{form.CustomerRefFullName|as_crispy_field}}
+
+
+
{{form.CustomerRefFullName|as_crispy_field}}
+
{{form.CustomerRefFullName|as_crispy_field}}
+
{{form.CustomerRefFullName|as_crispy_field}}
+
+
+
Outer row 1, column 3 - spans two rows (column 2 has two rows)
+
+
+ {% endcomment %} \ No newline at end of file diff --git a/django/Invoice/tests.py b/django/Invoice/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/django/Invoice/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/django/Invoice/urls.py b/django/Invoice/urls.py new file mode 100644 index 0000000..cd84006 --- /dev/null +++ b/django/Invoice/urls.py @@ -0,0 +1,19 @@ +from django.urls import path +from . import views + +app_name = "Invoice" + +urlpatterns = [ + # path('', views.home_view ), + path('', views.show_customer, name="show_customer" ), + path('selectso', views.select_so, name="select_so" ), + path('showinv', views.show_inv, name="show_inv" ), + + + path('', views.index, name="index"), + path('add', views.add_so, name="add_so"), + path('edit/', views.add_so, name="edit_so"), + path('delete/', views.delete_so, name="delete_so"), + path('getpricelist/', views.getpricelist_so, name="getpricelist_so"), + path('getpricelist/', views.getpricelist_so, name="getpricelist"), +] \ No newline at end of file diff --git a/django/Invoice/views.py b/django/Invoice/views.py new file mode 100644 index 0000000..2745c3d --- /dev/null +++ b/django/Invoice/views.py @@ -0,0 +1,300 @@ +from django.shortcuts import render, get_object_or_404, redirect +from django.urls import reverse +from django.http import HttpResponse, JsonResponse +from django.forms import modelformset_factory, inlineformset_factory +from django.db import transaction +from django.core import serializers +from .models import Invoice, InvoiceItemLine +from Item.models import Item, PriceLevel, PriceLevelItem +from Customer.models import Customer +from .forms import InvoiceForm, InvoiceItemLineForm, GeeksForm +import json +from django.core.serializers.json import DjangoJSONEncoder +from django.contrib import messages +import os +import pandas as pd + + +def show_customer(request): + pass + + thispath = os.getcwd() + print(thispath) + parent = os.path.dirname(thispath) + print(parent) + customers_file = os.path.join(parent, "ItemInventory", "CustomerList.xlsx") + df = pd.read_excel(customers_file, usecols=["FullName"]) + + context={"customers": df.values.tolist()} + if request.method =="POST": + import sys + sys.path.append('..') + from SO_to_Inv.readSO import SalesOrderQuery + print(os.getcwd()) + parentdir = os.path.dirname(os.getcwd()) + print(parentdir) + + + customer_name = request.POST.get("customerreffullname") + print(f'customer_name: {customer_name}') + context['objects'] = ['abc', 'def', 'ghi', 'jkl'] + if customer_name: + ini=SalesOrderQuery(FullName= customer_name, IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'TxnDate', 'RefNumber', 'IsManuallyClosed', 'IsFullyInvoiced','TotalAmount'], cwd=parentdir) + print("after ini") + # qbxml = ini.create_QBXML() + # print(qbxml) + response_string = ini.connect_to_quickbooks(ini.create_QBXML()) + print(response_string) + open_sales_orders = ini.get_open_so() + print(f'open sales orders:{open_sales_orders}') + ini=None + if open_sales_orders: + context['objects'] = open_sales_orders + + + context['customer_fullname'] = customer_name + return render(request, "Invoice/so_list_form.html", context) + # print(df.values.tolist()) + + + + return render(request, "Invoice/show-customers.html", context) + + +def select_so(request): + pass + +def show_inv(request): + print("show_inv") + context={} + if request.method == "POST": + print(request.POST) + if ('so_field' in request.POST) and ('customer_fullname' in request.POST): + # print(request.POST.getlist('so_field')) + multivals = request.POST.getlist('so_field') + customer_fullname = request.POST.get('customer_fullname') + print(f'Customer_fullname:{customer_fullname} -> request values:{multivals}') + return render( request, "Invoice/so_list_form.html", context) + # return HttpResponse('') + +def index(request): + print("index Inv") + context = {} + context['objects'] = Invoice.objects.order_by('-TimeCreated') + context['addurl'] = reverse('Invoice:add_so') + return render(request, "Invoice/index_invoice.html", context=context) +DEMO_CHOICES2 =( + ("10", "Naveen"), + ("20", "Pranav"), + ("30", "Isha"), + ("40", "Saloni"), + ("50", "Sg"), +) +def home_view(request): + if request.method == "POST": + print(request.POST) + if 'geeks_field' in request.POST: + print(request.POST.getlist('geeks_field')) + multivals = request.POST.getlist('geeks_field') + print(multivals) + form = GeeksForm(request.POST) + if form.is_valid(): + print('good') + demochc = () + for i in range(2,6): + demochc += ((i, str(i))) + context = {} + print (demochc) + form = GeeksForm() + # form.fields['geeks_field'].choices = demochc + context['form'] = form + return render( request, "Invoice/home.html", context) + +def add_so(request, pk=None): + print("add INV") + context = {} + obj=None + plname = None + if pk: + obj = get_object_or_404(Invoice.objects.select_related(), pk=pk) + # obj = get_object_or_404(Invoice, pk=pk) + plname = obj.CustomerRefFullName.PriceLevelRefFullName.Name + # print(f"{obj.CustomerRefFullName.PriceLevelRefFullName.Name}") + form = InvoiceForm(request.POST or None, instance=obj) + # InvoiceItemLineFormset = modelformset_factory(InvoiceItemLine, form=InvoiceItemLineForm, extra=0) #cannot use extra >0 because the formset is zip with the qs below + InvoiceItemLineFormset = inlineformset_factory(Invoice, InvoiceItemLine, form=InvoiceItemLineForm, extra=0) #cannot use extra >0 because the formset is zip with the qs below + # InvoiceItemLineFormset = modelformset_factory(InvoiceItemLine, fields = ('ItemRefFullName', 'Desc', 'Quantity', 'UnitOfMeasure', 'Rate', 'Amount', 'Invoiced', 'LineIsManuallyClosed',), extra=1) + # InvoiceItemLineFormset = modelformset_factory(InvoiceItemLine, fields = ('ItemRefFullName', 'Desc', 'Quantity', 'UnitOfMeasure', 'Rate', 'Amount', 'Invoiced', 'LineIsManuallyClosed',), extra=1) + qs=None + formset = InvoiceItemLineFormset(request.POST or None) + if pk: + print("got ID") + qs = obj.invoiceitemline_set.all().order_by('id').select_related('ItemRefFullName') + # formset = InvoiceItemLineFormset(request.POST or None, queryset=qs) + formset = InvoiceItemLineFormset(request.POST or None, instance=obj) + print(request.POST) + # print(formset) + # print(len(formset)) + # print(f"queryset={qs}") + # print(f"queryset={qs[0].ItemRefFullName}") + # qsItemList = list(x.ItemRefFullName for x in qs) + # print(qsItemList) + print(f'plname:{plname}') + qsIn = Item.objects.filter(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values('id', 'FullName','SalesDesc', 'SalesPrice', 'itempricelevel__Price') + qsEx = Item.objects.exclude(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values( "id", "FullName", "SalesDesc", "SalesPrice", "AlwaysNull") + # print(qsIn) + # print("qsEx") + # print(qsEx) + context['itemdatalist'] = qsIn.union(qsEx) + + context['object'] = obj + context['qsformset'] = None + if pk: + context['qsformset'] = list(zip(qs, formset)) + if request.method == "POST": + with transaction.atomic(): + if form.is_valid(): + # print(form.cleaned_data) + # with transaction.atomic(): + # print(formset) + if formset.is_valid(): + for delform in formset.deleted_forms: + pass + totalamount=form.cleaned_data['TotalAmount'] + print(totalamount, type(totalamount)) + totalamountChildren=0 + for fm in formset: + # print(fm) + print(fm['DELETE'].value()) + if not fm['DELETE'].value() and 'Amount' in fm.cleaned_data: + # print(fm.cleaned_data['Amount']) + amount=fm.cleaned_data['Amount'] + # print(amount) + print(fm['DELETE'].value()) + totalamountChildren+=amount + print(totalamountChildren) + if totalamount==totalamountChildren: + print("correct total amount") + else: + print(f"not correct total amount:{totalamount} supposed={totalamountChildren}") + # form.cleaned_data['TotalAmount'] = totalamountChildren + parentobj = form.save(commit=False) + parentobj.TotalAmount = totalamountChildren + parentobj.save() + # print(parentobj) + print("formset valid") + instances = formset.save(commit=False) + for obj in formset.deleted_objects: + print("deelted object") + print(obj) + obj.delete() + for instance in instances: + # print(instance.ItemRefFullName) + # print(instance.pk) + # print(parentobj.id) + instance.Invoice = parentobj + instance.save() + context['message'] = "All Data Saved" + print("all formset saved") + print(parentobj.pk, type(parentobj.pk)) + print(reverse('Invoice:edit_so', args=[parentobj.pk])) + messages.success(request, "All Data is Saved") + return redirect(reverse('Invoice:edit_so', args=[parentobj.pk])) + else: + print("formset error") + print(formset.errors) + else: + print("form error") + print(form.errors) + context['form'] = form + context['formset'] = formset + return render(request, "Invoice/create-update.html", context=context) + +# def add_so(request): +# print("create SO") +# context = {} +# # obj = get_object_or_404(Invoice, pk=id) +# obj=None +# form = InvoiceForm(request.POST or None, ) +# InvoiceItemLineFormset = modelformset_factory(InvoiceItemLine, form=InvoiceItemLineForm, extra=1) +# # qs = obj.invoiceitemline_set.all() +# qs=None +# formset = InvoiceItemLineFormset(request.POST or None, ) +# context['form'] = form +# context['formset'] = formset +# context['object'] = obj + +# if all([form.is_valid(), formset.is_valid()]): +# print(form.cleaned_data) +# for form in formset: +# print(form.clean_data) +# context['message'] = "All Data saved" +# return render(request, "Invoice/create-update.html", context=context) + + +def getpricelist_so(request, pk=None): + print(f"getpricelist INV; pk={pk}") + context = {} + obj=None + plname = None + if pk: + # obj = get_object_or_404(Invoice.objects.select_related(), pk=pk) + obj = get_object_or_404(Customer.objects.select_related(), pk=pk) + plname = obj.PriceLevelRefFullName.Name + # print(f"{obj.CustomerRefFullName.PriceLevelRefFullName.Name}") + # form = InvoiceForm(request.POST or None, instance=obj) + # InvoiceItemLineFormset = inlineformset_factory(Invoice, InvoiceItemLine, form=InvoiceItemLineForm, extra=0) #cannot use extra >0 because the formset is zip with the qs below + print(obj) + qs=None + # formset = InvoiceItemLineFormset(request.POST or None) + # if pk: + # print("got ID") + # qs = obj.invoiceitemline_set.all().order_by('id').select_related('ItemRefFullName') + # # formset = InvoiceItemLineFormset(request.POST or None, queryset=qs) + # formset = InvoiceItemLineFormset(request.POST or None, instance=obj) + print(request.GET) + # print(len(formset)) + # print(f"queryset={qs}") + # print(f"queryset={qs[0].ItemRefFullName}") + # qsItemList = list(x.ItemRefFullName for x in qs) + # print(qsItemList) + print(f'plname1:{plname}') + qsIn = Item.objects.filter(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values('id', 'FullName','SalesDesc', 'SalesPrice', 'itempricelevel__Price') + qsEx = Item.objects.exclude(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values( "id", "FullName", "SalesDesc", "SalesPrice", "AlwaysNull") + context['itemdatalist'] = qsIn.union(qsEx) + serialized_q = json.dumps(list( context['itemdatalist']), cls=DjangoJSONEncoder) + # p=json.loads(serialized_q) + print(f'serialized_q:{serialized_q}') + serialized_obj = serializers.serialize('json', [ obj, ]) + context['obj'] = serialized_obj + context['itemdatalist'] = serialized_q + # serialized_q = serialized_q + serialized_obj + # print(serialized_obj) + data = json.dumps(context, indent=4, sort_keys=True, default=str) + # print(data) + # print(serialized_q) + return JsonResponse(data, safe=False) + +def edit_so(request): + print("Edit SO") + context = {} + obj = get_object_or_404(Invoice, pk=id) + form = InvoiceForm(request.POST or None, instance=obj) + InvoiceItemLineFormset = modelformset_factory(InvoiceItemLine, form=InvoiceItemLineForm, extra=1) + qs = obj.invoiceitemline_set.all() + formset = InvoiceItemLineFormset(request.POST or None, isinstance=qs) + context['form'] = form + context['formset'] = formset + context['object'] = obj + + if all([form.is_valid(), formset.is_valid()]): + print(form.cleaned_data) + for form in formset: + print(form.clean_data) + context['message'] = "All Data saved" + return render(request, "Invoice/create-update.html", context=context) + +def delete_so(request): + pass + + diff --git a/django/Item/__init__.py b/django/Item/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django/Item/admin.py b/django/Item/admin.py new file mode 100644 index 0000000..e44f6fd --- /dev/null +++ b/django/Item/admin.py @@ -0,0 +1,19 @@ +from django.contrib import admin +from .models import UOM, Item, PriceLevel, PriceLevelItem + +class ItemAdmin(admin.ModelAdmin): + list_filter = ("ItemType",) +admin.site.register(UOM) +admin.site.register(Item, ItemAdmin) + +class PriceLevelPriceLevelItemInline(admin.TabularInline): + model = PriceLevelItem + readonly_fields = ('id',) + extra = 1 + +# admin.site.register(PriceLevel) +admin.site.register(PriceLevelItem) + +@admin.register(PriceLevel) +class PriceLevelAdmin(admin.ModelAdmin): + inlines = [PriceLevelPriceLevelItemInline] \ No newline at end of file diff --git a/django/Item/apps.py b/django/Item/apps.py new file mode 100644 index 0000000..052d043 --- /dev/null +++ b/django/Item/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ItemConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'Item' diff --git a/django/Item/forms.py b/django/Item/forms.py new file mode 100644 index 0000000..2434c0e --- /dev/null +++ b/django/Item/forms.py @@ -0,0 +1,44 @@ +from django.forms import ModelForm, Select +from django import forms +from crispy_forms.helper import FormHelper +from crispy_forms.layout import Layout, Submit, Row, Column, Field +from .models import Item, PriceLevel + +class ItemForm(ModelForm): + class Meta: + model = Item + fields = "__all__" + widgets = { + 'SalesDesc':forms.Textarea(attrs={'rows':4}), + 'PurchaseDesc':forms.Textarea(attrs={'rows':4}), + + } + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.helper = FormHelper() + self.helper.layout = Layout( + # Column('ItemType', css_class='form-group col-md-6 mb-0'), + Row( + Column('Name', css_class='form-group col-md-4 mb-0'), + Column('Parent', css_class='form-group col-md-4 mb-0'), + Column('ManufacturerPartNumber', css_class='form-group col-md-4 mb-0'), + css_class='form-row' + ), + Field('UnitOfMeasureSetRefFullName', css_class='form-input col-md-4 mb-0'), + # 'address_2', + Row( + # Card + Column('SalesDesc', css_class='form-group col-md-6 mb-0'), + Column('state', css_class='form-group col-md-4 mb-0'), + Column('zip_code', css_class='form-group col-md-2 mb-0'), + css_class='form-row' + ), + 'check_me_out', + Submit('submit', 'Sign in') + ) + +class PriceLevelForm(ModelForm): + class Meta: + model = PriceLevel + fields = "__all__" \ No newline at end of file diff --git a/django/Item/management/commands/__init__.py b/django/Item/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django/Item/management/commands/fillitems.py b/django/Item/management/commands/fillitems.py new file mode 100644 index 0000000..721e01b --- /dev/null +++ b/django/Item/management/commands/fillitems.py @@ -0,0 +1,103 @@ +from django.core.management.base import BaseCommand, CommandError +from Item.models import Item +import pandas as pd +import numbers as np + +class Command(BaseCommand): + help = "Closes the specified poll for voting" + def handle(self, *args, **options): + print("fill Items command") + + # return + # if request.method == 'POST' and request.FILES['myfile']: + # myfile = request.FILES['myfile'] + # fs = FileSystemStorage() + filename = "Item/management/commands/Iteminventory20230417.xls" + # filename = "Item/management/commands/Book2.xlsx" + # filename = fs.save(myfile.name, myfile) + # uploaded_file_url = fs.url(filename) + empexceldata = pd.read_excel(filename, converters={'ReorderPoint':int}, ) + + dbframe = empexceldata.replace("NaN", "") + dbframe = dbframe.fillna("") + print(dbframe['PurchaseCost']) + dbframe['PurchaseCost'] = dbframe['PurchaseCost'].apply(pd.to_numeric, downcast='float', errors='coerce') + dbframe['AverageCost'] = dbframe['AverageCost'].apply(pd.to_numeric, downcast='float', errors='coerce') + # dbframe['Reorderpoint'] = dbframe['ReorderPoint'].apply(pd.to_numeric, downcast='float', errors='coerce') + # dbframe['ReorderPoint'] = dbframe['ReorderPoint'].astype(int) + print (dbframe) + dbframe['PurchaseCost'] = dbframe['PurchaseCost'].fillna(0) + dbframe['AverageCost'] = dbframe['AverageCost'].fillna(0) + print(dbframe['PurchaseCost']) + # print(dbframe['NameFromTaco']) + # print(dbframe['ReorderPoint']) + print(dbframe['QuantityOnHand']) + print (dbframe.dtypes) + icount=0 + for db in dbframe.itertuples(): + obj, created = Item.objects.get_or_create(FullName=db.FullName) + print(obj.FullName, obj.pk) + # if created: + obj.ItemType=1 + obj.Name=db.Name + # obj.FullName=db.FullName + # obj.# BarCodeValue=db.# BarCodeValue + obj.SalesDesc=db.SalesDesc + # obj.# SalesPrice=db.# SalesPrice + obj.PurchaseDesc=db.PurchaseDesc + obj.Sublevel=db.Sublevel + obj.ManufacturerPartNumber=db.ManufacturerPartNumber + obj.PurchaseCost=db.PurchaseCost + # obj.ReorderPoint=db.ReorderPoint + obj.QuantityOnHand=db.QuantityOnHand + obj.AverageCost=db.AverageCost + obj.QuantityOnOrder=db.QuantityOnOrder + obj.QuantityOnSalesOrder=db.QuantityOnSalesOrder + # obj.# UnitOfMeasureSetRefFullName=db.# UnitOfMeasureSetRefFullName + obj.ParentRefFullName=db.ParentRefFullName + # obj.# SalesTaxCodeRefFullName=db.# SalesTaxCodeRefFullName + obj.IncomeAccountRefFullName=db.IncomeAccountRefFullName + obj.COGSAccountRefFullName=db.COGSAccountRefFullName + obj.PrefVendorRefFullName=db.PrefVendorRefFullName + obj.AssetAccountRefFullName=db.AssetAccountRefFullName + obj.IsActive=db.IsActive + obj.NameFromTaco=db.NameFromTaco + obj.CATEGORY=db.CATEGORY + obj.Type=db.Type + + # obj = Item.objects.create(Name = db.Name, + # FullName = db.FullName, + # # BarCodeValue = db.# BarCodeValue, + # SalesDesc = db.SalesDesc, + # # SalesPrice = db.# SalesPrice, + # PurchaseDesc = db.PurchaseDesc, + # Sublevel = db.Sublevel, + # ManufacturerPartNumber = db.ManufacturerPartNumber, + # PurchaseCost = db.PurchaseCost, + # # ReorderPoint = db.ReorderPoint, + # QuantityOnHand = db.QuantityOnHand, + # AverageCost = db.AverageCost, + # QuantityOnOrder = db.QuantityOnOrder, + # QuantityOnSalesOrder = db.QuantityOnSalesOrder, + # # UnitOfMeasureSetRefFullName = db.# UnitOfMeasureSetRefFullName, + # ParentRefFullName = db.ParentRefFullName, + # # SalesTaxCodeRefFullName = db.# SalesTaxCodeRefFullName, + # IncomeAccountRefFullName = db.IncomeAccountRefFullName, + # COGSAccountRefFullName = db.COGSAccountRefFullName, + # PrefVendorRefFullName = db.PrefVendorRefFullName, + # AssetAccountRefFullName = db.AssetAccountRefFullName, + # IsActive = db.IsActive, + # NameFromTaco = db.NameFromTaco, + # CATEGORY = db.CATEGORY, + # Type = db.Type, + # ) + obj.save() + icount+=1 + print(f"{icount} Records updated/added") + + + + # return render(request, 'Import_excel_db.html', { + # 'uploaded_file_url': uploaded_file_url + # }) + # return render(request, 'Import_excel_db.html',{}) \ No newline at end of file diff --git a/django/Item/migrations/0001_initial.py b/django/Item/migrations/0001_initial.py new file mode 100644 index 0000000..c6c4964 --- /dev/null +++ b/django/Item/migrations/0001_initial.py @@ -0,0 +1,60 @@ +# Generated by Django 4.2 on 2023-05-02 15:17 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='UOM', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('Name', models.CharField(max_length=80)), + ('Abbreviation', models.CharField(max_length=12)), + ('Number_of', models.DecimalField(decimal_places=3, max_digits=12)), + ('Parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='parent', to='Item.uom')), + ('Purchases', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='purchases', to='Item.uom')), + ('Sales', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='sales', to='Item.uom')), + ], + ), + migrations.CreateModel( + name='Item', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('ItemType', models.CharField(choices=[('3', 'SERVICE'), ('1', 'INVENTORY PART'), ('2', 'NON INVENTORY'), ('4', 'OTHER CHARGES'), ('5', 'SUB TOTAL'), ('6', 'GROUP'), ('7', 'DISCOUNT'), ('8', 'PAYMENT')], default='3', max_length=1)), + ('Name', models.CharField(max_length=80)), + ('FullName', models.CharField(blank=True, max_length=80, null=True, unique=True)), + ('SalesDesc', models.CharField(blank=True, max_length=80, null=True)), + ('SalesPrice', models.DecimalField(decimal_places=2, default=0, max_digits=10)), + ('PurchaseDesc', models.CharField(blank=True, max_length=80, null=True)), + ('Sublevel', models.PositiveSmallIntegerField(default=0)), + ('ManufacturerPartNumber', models.CharField(blank=True, max_length=80, null=True)), + ('PurchaseCost', models.DecimalField(decimal_places=2, default=0, max_digits=10)), + ('ReorderPoint', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)), + ('QuantityOnHand', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)), + ('AverageCost', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)), + ('QuantityOnOrder', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)), + ('QuantityOnSalesOrder', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)), + ('ParentRefFullName', models.CharField(max_length=80)), + ('IncomeAccountRefFullName', models.CharField(default='Sales', max_length=80)), + ('COGSAccountRefFullName', models.CharField(default='COGS', max_length=80)), + ('PrefVendorRefFullName', models.CharField(default='TACO', max_length=80)), + ('AssetAccountRefFullName', models.CharField(default='Inventory Asset', max_length=80)), + ('IsActive', models.BooleanField(default=True)), + ('NameFromTaco', models.CharField(blank=True, max_length=60, null=True)), + ('CATEGORY', models.CharField(blank=True, max_length=60, null=True)), + ('Type', models.CharField(blank=True, max_length=60, null=True)), + ('TimeCreated', models.DateTimeField(auto_now_add=True)), + ('TimeModified', models.DateTimeField(auto_now=True)), + ('Parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='Item.item')), + ('UnitOfMeasureSetRefFullName', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='Item.uom')), + ], + ), + ] diff --git a/django/Item/migrations/0002_alter_item_parentreffullname.py b/django/Item/migrations/0002_alter_item_parentreffullname.py new file mode 100644 index 0000000..a5571d1 --- /dev/null +++ b/django/Item/migrations/0002_alter_item_parentreffullname.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-05-02 15:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Item', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='item', + name='ParentRefFullName', + field=models.CharField(blank=True, max_length=80, null=True), + ), + ] diff --git a/django/Item/migrations/0003_alter_uom_number_of.py b/django/Item/migrations/0003_alter_uom_number_of.py new file mode 100644 index 0000000..94f05a4 --- /dev/null +++ b/django/Item/migrations/0003_alter_uom_number_of.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-05-03 13:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Item', '0002_alter_item_parentreffullname'), + ] + + operations = [ + migrations.AlterField( + model_name='uom', + name='Number_of', + field=models.DecimalField(blank=True, decimal_places=3, max_digits=12, null=True), + ), + ] diff --git a/django/Item/migrations/0004_alter_uom_name.py b/django/Item/migrations/0004_alter_uom_name.py new file mode 100644 index 0000000..caf5eb3 --- /dev/null +++ b/django/Item/migrations/0004_alter_uom_name.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-05-03 13:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Item', '0003_alter_uom_number_of'), + ] + + operations = [ + migrations.AlterField( + model_name='uom', + name='Name', + field=models.CharField(blank=True, max_length=80, null=True), + ), + ] diff --git a/django/Item/migrations/0005_alter_item_itemtype.py b/django/Item/migrations/0005_alter_item_itemtype.py new file mode 100644 index 0000000..3e1b615 --- /dev/null +++ b/django/Item/migrations/0005_alter_item_itemtype.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-05-04 16:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Item', '0004_alter_uom_name'), + ] + + operations = [ + migrations.AlterField( + model_name='item', + name='ItemType', + field=models.CharField(choices=[('3', 'SERVICE'), ('1', 'INVENTORY PART'), ('2', 'NON INVENTORY'), ('4', 'OTHER CHARGES'), ('5', 'SUB TOTAL'), ('6', 'GROUP'), ('7', 'DISCOUNT'), ('8', 'PAYMENT')], max_length=1), + ), + ] diff --git a/django/Item/migrations/0006_alter_item_unitofmeasuresetreffullname.py b/django/Item/migrations/0006_alter_item_unitofmeasuresetreffullname.py new file mode 100644 index 0000000..fa0cd6f --- /dev/null +++ b/django/Item/migrations/0006_alter_item_unitofmeasuresetreffullname.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2 on 2023-05-04 20:53 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('Item', '0005_alter_item_itemtype'), + ] + + operations = [ + migrations.AlterField( + model_name='item', + name='UnitOfMeasureSetRefFullName', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='Item.uom', verbose_name='UOM'), + ), + ] diff --git a/django/Item/migrations/0007_pricelevel_pricelevelitem.py b/django/Item/migrations/0007_pricelevel_pricelevelitem.py new file mode 100644 index 0000000..ddf6dcf --- /dev/null +++ b/django/Item/migrations/0007_pricelevel_pricelevelitem.py @@ -0,0 +1,35 @@ +# Generated by Django 4.2 on 2023-05-08 05:20 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('Item', '0006_alter_item_unitofmeasuresetreffullname'), + ] + + operations = [ + migrations.CreateModel( + name='PriceLevel', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('Name', models.CharField(max_length=50)), + ('Desc', models.CharField(blank=True, max_length=180, null=True, verbose_name='Description')), + ('TimeCreated', models.DateTimeField(auto_now_add=True)), + ('TimeModified', models.DateTimeField(auto_now=True)), + ], + ), + migrations.CreateModel( + name='PriceLevelItem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('Price', models.DecimalField(decimal_places=2, max_digits=12)), + ('TimeCreated', models.DateTimeField(auto_now_add=True)), + ('TimeModified', models.DateTimeField(auto_now=True)), + ('IPL', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='itempricelevel', to='Item.item')), + ('PL', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pricelevel', to='Item.pricelevel')), + ], + ), + ] diff --git a/django/Item/migrations/0008_alter_pricelevelitem_pl.py b/django/Item/migrations/0008_alter_pricelevelitem_pl.py new file mode 100644 index 0000000..2f44cec --- /dev/null +++ b/django/Item/migrations/0008_alter_pricelevelitem_pl.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2 on 2023-05-08 05:22 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('Item', '0007_pricelevel_pricelevelitem'), + ] + + operations = [ + migrations.AlterField( + model_name='pricelevelitem', + name='PL', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pricelevel', to='Item.pricelevel'), + ), + ] diff --git a/django/Item/migrations/0009_item_alwaysnull.py b/django/Item/migrations/0009_item_alwaysnull.py new file mode 100644 index 0000000..8ff2952 --- /dev/null +++ b/django/Item/migrations/0009_item_alwaysnull.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-05-08 22:11 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Item', '0008_alter_pricelevelitem_pl'), + ] + + operations = [ + migrations.AddField( + model_name='item', + name='AlwaysNull', + field=models.CharField(blank=True, editable=False, max_length=1, null=True), + ), + ] diff --git a/django/Item/migrations/0010_alter_pricelevelitem_price.py b/django/Item/migrations/0010_alter_pricelevelitem_price.py new file mode 100644 index 0000000..b58d7ee --- /dev/null +++ b/django/Item/migrations/0010_alter_pricelevelitem_price.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-05-10 20:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Item', '0009_item_alwaysnull'), + ] + + operations = [ + migrations.AlterField( + model_name='pricelevelitem', + name='Price', + field=models.DecimalField(decimal_places=2, max_digits=12, null=True), + ), + ] diff --git a/django/Item/migrations/__init__.py b/django/Item/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django/Item/models.py b/django/Item/models.py new file mode 100644 index 0000000..41d57fc --- /dev/null +++ b/django/Item/models.py @@ -0,0 +1,140 @@ +from django.db import models +from django.db import IntegrityError +from django.core.exceptions import ValidationError +from django.urls import reverse + +class PriceLevel(models.Model): + Name = models.CharField(max_length=50) + Desc = models.CharField(max_length=180, verbose_name="Description", blank=True, null=True) + TimeCreated = models.DateTimeField(auto_now_add=True) + TimeModified = models.DateTimeField(auto_now=True) + + def __str__(self): + return f"{self.pk}; {self.Name}" + + def get_field_name(obj): + # return [(f.name, f.value_to_string(obj)) for f in obj._meta.fields] #get value convert it to string + return [(f.verbose_name, f.name, f.value_from_object(obj)) for f in obj._meta.fields] + + def get_absolute_url(self): + return reverse('Item:edit_pricelevel', args=[str(self.id)]) + +class PriceLevelItem(models.Model): + PL = models.ForeignKey("PriceLevel", related_name="pricelevel", on_delete=models.CASCADE) + IPL = models.ForeignKey("Item", related_name="itempricelevel", on_delete=models.CASCADE) + Price = models.DecimalField(max_digits=12, decimal_places=2, null=True) + TimeCreated = models.DateTimeField(auto_now_add=True) + TimeModified = models.DateTimeField(auto_now=True) + + #class meta pl ipl unique together + def __str__(self): + return f"{self.PL.Name}; {self.IPL.FullName}; {self.Price}" + +class UOM(models.Model): + Name = models.CharField(max_length=80, blank=True, null=True) + Abbreviation = models.CharField(max_length=12) + Number_of = models.DecimalField(max_digits=12, decimal_places=3, blank=True, null=True) + Parent = models.ForeignKey("UOM", related_name="parent", on_delete=models.DO_NOTHING, blank=True, null=True) + Purchases = models.ForeignKey("UOM", related_name="purchases", on_delete=models.DO_NOTHING, blank=True, null=True) + Sales = models.ForeignKey("UOM", related_name="sales", on_delete=models.DO_NOTHING, blank=True, null=True) + + def __str__(self): + return self.Abbreviation + +class Item(models.Model): + ITEMINVENTORY = "1" + NONINVENTORY = "2" + SERVICE = "3" + OTHERCHARGES = "4" + SUBTOTAL = "5" + GROUP = "6" + DISCOUNT = "7" + PAYMENT = "8" + ITEM_TYPE_CHOICES = [ + (SERVICE, "SERVICE"), + (ITEMINVENTORY, "INVENTORY PART"), + (NONINVENTORY, "NON INVENTORY"), + (OTHERCHARGES, "OTHER CHARGES"), + (SUBTOTAL, "SUB TOTAL"), + (GROUP, "GROUP"), + (DISCOUNT, "DISCOUNT"), + (PAYMENT, "PAYMENT"), + ] + ItemType = models.CharField(max_length=1, choices=ITEM_TYPE_CHOICES) + Name = models.CharField(max_length=80) + Parent = models.ForeignKey("Item", on_delete=models.DO_NOTHING, blank=True, null=True) + FullName = models.CharField(max_length=80, blank=True, null=True, unique=True) + # BarCodeValue = models.CharField(max_length=80) + SalesDesc = models.CharField(max_length=80, blank=True, null=True) + SalesPrice = models.DecimalField(max_digits=10, decimal_places=2, default=0) + PurchaseDesc = models.CharField(max_length=80, blank=True, null=True) + Sublevel = models.PositiveSmallIntegerField(default = 0) + ManufacturerPartNumber = models.CharField(max_length=80, blank=True, null=True) + PurchaseCost = models.DecimalField(max_digits=10, decimal_places=2, default=0) + ReorderPoint = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True) + QuantityOnHand = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True) + AverageCost = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True) + QuantityOnOrder = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True) + QuantityOnSalesOrder = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True) + UnitOfMeasureSetRefFullName = models.ForeignKey(UOM, verbose_name="UOM", on_delete=models.DO_NOTHING, blank=True, null=True) + ParentRefFullName = models.CharField(max_length=80, blank=True, null=True) + # SalesTaxCodeRefFullName + IncomeAccountRefFullName= models.CharField(max_length=80, default="Sales") + COGSAccountRefFullName = models.CharField(max_length=80, default="COGS") + PrefVendorRefFullName = models.CharField(max_length=80, default="TACO") + AssetAccountRefFullName = models.CharField(max_length=80, default="Inventory Asset") + IsActive = models.BooleanField(default=True) + NameFromTaco = models.CharField(max_length=60, blank=True, null=True) + CATEGORY = models.CharField(max_length=60, blank=True, null=True) + Type = models.CharField(max_length=60, blank=True, null=True) + AlwaysNull = models.CharField(max_length=1, blank=True, null=True, editable=False) + TimeCreated = models.DateTimeField(auto_now_add=True) + TimeModified = models.DateTimeField(auto_now=True) + + # class Meta: + # ordering = ["FullName"] + + def get_field_name(obj): + # return [(f.name, f.value_to_string(obj)) for f in obj._meta.fields] #get value convert it to string + return [(f.verbose_name, f.name, f.value_from_object(obj)) for f in obj._meta.fields] + + def save(self, *args, **kwargs): + try: + self.FullName = self.Name + print(f"self.FullName={self.FullName}; self.parentreffullname={self.ParentRefFullName}; self.pk={self.pk}") + if self.ParentRefFullName: + print("masuk") + parent = Item.objects.filter(FullName__iexact=self.ParentRefFullName)[0] + print(f"parent.fullname:{parent.FullName}") + + if parent: + print(parent.FullName) + self.Parent=parent + print(f"self.Parent={self.Parent}") + if self.Parent: + print(f"self.Parent={self.Parent}") + if self.Parent.FullName: + self.FullName = f"{self.Parent.FullName}:{self.Name}" #no need to do upper() + else: + self.FullName = f"{self.Parent.Name}:{self.Name}" + print(self.Parent.Name, self.Parent.FullName, self.FullName) + item = Item.objects.filter(FullName__iexact=self.FullName) + if item and not self.pk: #check for unique constrain + raise ValidationError("Item FullName should be Unique") #TODO again later + # return + print("raise validationerror itemfullname should unique") + print(f"{self.IsActive}; {self.PurchaseCost}; {self.ReorderPoint}") + super(Item, self).save(*args, **kwargs) + except IntegrityError: + print("integrity error") + except ValidationError: + print("valid error") + + def __str__(self) -> str: + if self.FullName: + return f"{self.FullName}" + else: + return self.Name + + def get_absolute_url(self): # // ---> new function + return reverse('Item:edit_item', args=[str(self.id)]) \ No newline at end of file diff --git a/django/Item/templates/Item/addedit_item.html b/django/Item/templates/Item/addedit_item.html new file mode 100644 index 0000000..fbbee32 --- /dev/null +++ b/django/Item/templates/Item/addedit_item.html @@ -0,0 +1,101 @@ +{% extends 'base.html' %} +{% load crispy_forms_tags %} + +{% block title %}{{title}}{% endblock title %} + +{% block body %} +
+ {% csrf_token %} + {% comment %} {% crispy form %} {% endcomment %} + {% comment %} {{form|crispy}} {% endcomment %} +
+
+
+
+
{{form.ItemType|as_crispy_field}}
+
+
+
+
{{form.IsActive|as_crispy_field}}
+
+ +
+
+
+
{{form.Name|as_crispy_field}}
+
{{form.Parent|as_crispy_field}}
+
{{form.ManufacturerPartNumber|as_crispy_field}}
+
+
+
+
+
{{form.UnitOfMeasureSetRefFullName|as_crispy_field}}
+
+
+ +
+
+
+
{{form.PurchaseDesc|as_crispy_field}}
+
{{form.PurchaseCost|as_crispy_field}}
+
{{form.COGSAccountRefFullName|as_crispy_field}}
+
{{form.PrefVendorRefFullName|as_crispy_field}}
+
+
+
+
+
{{form.SalesDesc|as_crispy_field}}
+
{{form.SalesPrice|as_crispy_field}}
+
+
{{form.IncomeAccountRefFullName|as_crispy_field}}
+ +
+
+
+
+
+
{{form.IncomeAccountRefFullName|as_crispy_field}}
+
{{form.ReorderPoint|as_crispy_field}}
+
{{form.ReorderPoint|as_crispy_field}}
+
{{form.QuantityOnHand|as_crispy_field}}
+
{{form.AverageCost|as_crispy_field}}
+
{{form.QuantityOnOrder|as_crispy_field}}
+
{{form.QuantityOnSalesOrder|as_crispy_field}}
+
+
+ + + + + + + + +
+
+{% endblock body %} + diff --git a/django/Item/templates/Item/addedit_pricelevel.html b/django/Item/templates/Item/addedit_pricelevel.html new file mode 100644 index 0000000..32ff1b0 --- /dev/null +++ b/django/Item/templates/Item/addedit_pricelevel.html @@ -0,0 +1,173 @@ +{% extends 'base.html' %} +{% load crispy_forms_tags %} + +{% block title %}Price Level{% endblock title %} + +{% block search_nav %} + + + {% with objects as items %} + {% for item in items %} + {% comment %} {{item.FullName}} {% endcomment %} + + {% endfor %} + {% endwith %} +{% endblock search_nav %} + +{% block body %} +
+ {% csrf_token %} + {{form|crispy}} +
+ + + + + + + + {% for obj in objects %} + + + + + + {% endfor %} + +
FullNameSalesPricePrice
+
+
+ +
+ + + + + +{% endblock body %} \ No newline at end of file diff --git a/django/Item/templates/Item/index.html b/django/Item/templates/Item/index.html new file mode 100644 index 0000000..3a1ceca --- /dev/null +++ b/django/Item/templates/Item/index.html @@ -0,0 +1 @@ +{% include "Item/table_index.html" with title="Item Index" %} \ No newline at end of file diff --git a/django/Item/templates/Item/index_pricelevel.html b/django/Item/templates/Item/index_pricelevel.html new file mode 100644 index 0000000..6cd886c --- /dev/null +++ b/django/Item/templates/Item/index_pricelevel.html @@ -0,0 +1 @@ +{% include 'Item/table_index.html' with title="Price Level Index" %} \ No newline at end of file diff --git a/django/Item/templates/Item/table_index.html b/django/Item/templates/Item/table_index.html new file mode 100644 index 0000000..e7f3661 --- /dev/null +++ b/django/Item/templates/Item/table_index.html @@ -0,0 +1,221 @@ +{% extends 'base.html' %} +{% load tz %} + +{% block title %} + {{title}} +{% endblock title %} + +{% block search_nav %} + + + + {% for item in items %} + {{item.FullName}} + " + {% endfor %} + +{% endblock search_nav %} + + +{% block body %} +
+
+ Add New +
+
+ + + {% for verbose_name, key, val in objects.0.get_field_name %} + + {% endfor %} + + + + {% for object in objects %} + + {% for vn, key, val in object.get_field_name %} + {% if forloop.first %} + {% comment %} {% endcomment %} + + {% else %} + {% if key == "TimeModified" or key == "TimeCreated" %} + + {% elif key == "ItemType" %} + + {% else %} + + {% endif %} + {% endif %} + {% endfor %} + + {% endfor %} + +
{{verbose_name}}
{{object.Name|safe}} + {% if object.Name %} + {{object.Name|safe}} + {% elif object.CustomerName %} + {{object.CustomerName}} + {% elif object.RefNumber %} + {{object.RefNumber}} + {% endif %} + {{val|localtime}}{{object.get_ItemType_display}}{{val}}
+
+
+ + + {% if objects.paginator.num_pages > 1 %} +
+ +
+ {% endif %} + +
+ test +
+ + + + + +{% endblock body %} \ No newline at end of file diff --git a/django/Item/tests.py b/django/Item/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/django/Item/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/django/Item/urls.py b/django/Item/urls.py new file mode 100644 index 0000000..3003f54 --- /dev/null +++ b/django/Item/urls.py @@ -0,0 +1,14 @@ +from django.urls import path, include +from .views import index, add_item, edit_item, delete_item, edit_pricelevel, add_pricelevel, index_pricelevel +app_name = "Item" +urlpatterns = [ + + path('', index, name="index"), + path('add', add_item, name="add_item"), + path('edit/', edit_item, name="edit_item"), + path('delete/', delete_item, name="delete_item"), + path('pricelevel/', index_pricelevel, name="index_pricelevel"), + path('editpricelevel/', add_pricelevel, name="edit_pricelevel"), + path('addpricelevel/', add_pricelevel, name="add_pricelevel"), + +] diff --git a/django/Item/views.py b/django/Item/views.py new file mode 100644 index 0000000..e55522f --- /dev/null +++ b/django/Item/views.py @@ -0,0 +1,170 @@ +from django.shortcuts import render, redirect, get_object_or_404 +from django.http import HttpResponse +from django.urls import reverse +from django.db import transaction +from django.core.paginator import Paginator + +from django.db.models import Q + +from .models import Item, UOM +from .forms import ItemForm, PriceLevelForm + +from django.db.models import Q +from Item.models import Item, PriceLevel, PriceLevelItem +import json + +def index_pricelevel(request): + context={} + context['objects']=PriceLevel.objects.order_by('Name') + context['addurl'] = reverse('Item:add_pricelevel') + # print(context['objects']) + return render(request, "Item/index_pricelevel.html", context=context) + +def add_pricelevel(request, id=None): + context={} + # print(f"idroot={id}") + pricelevel1 = None + plname=None + context['pk'] = 'null' + if id: + print(f"edit id={id}") + pricelevel1=get_object_or_404(PriceLevel, pk=id) + plname= pricelevel1.Name + print(plname) + context['pk'] = pricelevel1.pk + else: + print("add new") + + form = PriceLevelForm(request.POST or None, instance=pricelevel1) + qs1 = Item.objects.filter(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values('FullName','SalesPrice', 'itempricelevel__Price') + qs2 = Item.objects.exclude(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values( "FullName", "SalesPrice", "AlwaysNull") + # print(qs2) + qs = qs1.union(qs2) + # print(type(qs)) + # print(qs) + context['objects'] = qs + context['form'] = form + if request.POST: + datas = request.POST.get('data') + pk = request.POST.get('pk') + print(pk) + with transaction.atomic(): + if form.is_valid(): + print(form.cleaned_data["Name"]) + pricelevel = form.save() + print("form pricelevel saved") + # return redirect(reverse("index")) + else: + print("form not valid") + return render(request, "Item/addedit_pricelevel.html", context=context) + + # pricelevel = get_object_or_404(PriceLevel, pk=pk) + + # print(f"pk={pk}; object={pricelevel}") + # print(type(datas)) + # print(datas) + datas = json.loads(datas) + # print(type(datas)) + # print(datas) + # print(form["Name"].value()) + blAllSaved = True + if len(datas)>0: + print("more than 0") + for data in datas: + print(type(data)) + print(data) + # print(data['FullName']) + if data['dtchange']=="1" or data['dtchange']=="2": + ## add new pricelevelitem + print("dtchange 1,2") + item = get_object_or_404(Item, FullName = f"{data['FullName']}") + print(f"object=={item}") + pricelevelitem, created = PriceLevelItem.objects.get_or_create(PL=pricelevel, IPL=item, defaults={'Price':data['price']}) + print(f"created={created}") + print(f"object=={pricelevelitem}") + if not created: + pricelevelitem.Price = data['price'] + pricelevelitem.save() + print(f"object=={pricelevelitem}") + else: + blAllSaved=False + print("dtchange is NOT 1 or 2") + if blAllSaved: + return redirect(reverse('Item:index_pricelevel')) + else: + return redirect(reverse('Item:edit_pricelevel', pricelevel.pk )) + else: + return redirect(reverse('Item:index_pricelevel')) + return render(request, "Item/addedit_pricelevel.html", context=context) + +def edit_pricelevel(request, pk): + context={} + qs1 = Item.objects.filter(itempricelevel__PL__Name='B2020',).prefetch_related("itempricelevel").values('FullName','SalesPrice', 'itempricelevel__Price') + qs2 = Item.objects.exclude(itempricelevel__PL__Name='B2020').prefetch_related("itempricelevel").values( "FullName", "SalesPrice", "AlwaysNull") + # print(qs2) + qs = qs1.union(qs2) + # print(type(qs)) + # print(qs) + context['objects'] = qs + return render(request, "Item/addedit_pricelevel.html", context=context) + + + +def index(request): + context={} + search = request.GET.get("q") + items=Item.objects.all().order_by('FullName') + if search: + item = Item.objects.order_by('FullName').filter(Q(Name__icontains=search) | Q(FullName__icontains=search)) + else: + item = Item.objects.order_by('FullName') + paginator = Paginator(item, 25) # Show 25 contacts per page. + page_number = request.GET.get("page") + page_obj = paginator.get_page(page_number) + # heads = [f.name for f in Item._meta.get_fields()] + # print(heads) + context['objects'] = page_obj + context['items'] = items + context['addurl'] = reverse('Item:add_item') + return render(request, "Item/index.html", context=context) + + +def add_item(request): + form = ItemForm(request.POST or None) + if request.POST: + print(form["Name"].value()) + if form.is_valid(): + print(form.cleaned_data["Name"]) + form.save() + return redirect(reverse("Item:index")) + print(form["Name"].value()) + return render(request, "Item/addedit_item.html", {"form":form}) + + +def delete_item(request, pk): + item = get_object_or_404(Item, pk=pk) + item.delete() + return HttpResponse(f"{pk} is deleted") + + +def edit_item(request, pk): + print(pk) + print(request) + item = get_object_or_404(Item, pk=pk) + form = ItemForm( request.POST or None, instance=item) + if request.method == "GET": + print("GET") + if item: + # form = ItemForm(instance=item) + return render(request, "Item/addedit_item.html", {"objects": [item,], "form":form}) + elif request.method == "POST": + print("POST") + # form = ItemForm(request.POST, instance=item) + if form.is_valid(): + print("form is valid") + item=form.save() + # return redirect(reverse('Item:edit_item', kwargs={"pk":pk})) + return render(request, "Item/index.html", {"objects": [item]}) + else: + print("not valid form") + return render(request, "Item/addedit_item.html", {"objects": [item,], "form":form}) diff --git a/django/SalesOrder/__init__.py b/django/SalesOrder/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django/SalesOrder/admin.py b/django/SalesOrder/admin.py new file mode 100644 index 0000000..e2b77e7 --- /dev/null +++ b/django/SalesOrder/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from .models import SalesOrder, SalesOrderItemLine + + +admin.site.register(SalesOrder) +admin.site.register(SalesOrderItemLine) \ No newline at end of file diff --git a/django/SalesOrder/apps.py b/django/SalesOrder/apps.py new file mode 100644 index 0000000..30955ef --- /dev/null +++ b/django/SalesOrder/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class SalesorderConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'SalesOrder' diff --git a/django/SalesOrder/forms.py b/django/SalesOrder/forms.py new file mode 100644 index 0000000..6681680 --- /dev/null +++ b/django/SalesOrder/forms.py @@ -0,0 +1,43 @@ +from django.forms import ModelForm +from django import forms +from .models import SalesOrder, SalesOrderItemLine +from crispy_forms.helper import FormHelper + +class SalesOrderForm(ModelForm): + class Meta: + model = SalesOrder + fields = "__all__" + widgets = { + 'TxnDate' : forms.DateInput(attrs={'type':"date"}), + 'BillAddr1' : forms.Textarea(attrs={'rows':7, 'style':'height:180px'}), + 'ShipAddr1' : forms.Textarea(attrs={'rows':7, 'style':'height:180px'}), + 'TotalAmount' : forms.TextInput(attrs={'class':'text-end hidden', 'onkeypress':'return event.preventDefault()'}) + } + def __init__(self, *args, **kwargs): + super(SalesOrderForm, self).__init__(*args, **kwargs) + self.helper = FormHelper(self) + # self.helper.form_show_labels = False + self.fields['TotalAmount'].label = False + self.fields['TotalAmount'].field_class = '' + +class SalesOrderItemLineForm(ModelForm): + class Meta: + model = SalesOrderItemLine + fields = ('ItemRefFullName', 'Desc', 'Quantity', 'UnitOfMeasure', 'Rate', 'Amount', 'Invoiced', 'LineIsManuallyClosed') + # fields = "__all__" + widgets = { + # 'ItemRefFullName' : forms.Select(choices=[('1', '1')]), + 'ItemRefFullName' : forms.NumberInput(attrs={'class':'hidden itemreffullname'}), + 'Desc' : forms.TextInput(attrs={'class':'desc'}), + 'Quantity' : forms.TextInput(attrs={'class':'quantity','onkeypress':'numberOnly(event)'}), #'onkeypress':'return (event.charCode >= 48 && event.charCode <= 57) || event.charCode == 46'}), + 'UnitOfMeasure' : forms.Select(attrs={'class':'unitofmeasure'}), + 'Rate' : forms.TextInput(attrs={'class':'rate text-end', 'onkeypress':'numberOnly(event)'}), + 'Amount' : forms.TextInput(attrs={'class':'amount text-end', 'onkeypress':'numberOnly(event)', 'onchange':'amountchanged(event)'}), + } + + def __init__(self, *args, **kwargs): + super(SalesOrderItemLineForm, self).__init__(*args, **kwargs) + self.helper = FormHelper(self) + self.helper.form_show_labels = False + # self.helper.form_class = "abc" + # self.helper.field_class = "xyz" \ No newline at end of file diff --git a/django/SalesOrder/migrations/0001_initial.py b/django/SalesOrder/migrations/0001_initial.py new file mode 100644 index 0000000..4cd3136 --- /dev/null +++ b/django/SalesOrder/migrations/0001_initial.py @@ -0,0 +1,82 @@ +# Generated by Django 4.2 on 2023-05-13 18:32 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('Item', '0010_alter_pricelevelitem_price'), + ('Customer', '0005_alter_customer_coordinates_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='SalesOrder', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('TxnDate', models.DateTimeField()), + ('RefNumber', models.CharField(max_length=30)), + ('BillAddr1', models.CharField(max_length=80)), + ('BillAddr2', models.CharField(blank=True, max_length=80, null=True)), + ('BillAddr3', models.CharField(blank=True, max_length=80, null=True)), + ('BillAddr4', models.CharField(blank=True, max_length=80, null=True)), + ('BillAddr5', models.CharField(blank=True, max_length=80, null=True)), + ('BillCity', models.CharField(blank=True, max_length=80, null=True)), + ('BillState', models.CharField(blank=True, max_length=80, null=True)), + ('BillPostalCode', models.CharField(blank=True, max_length=80, null=True)), + ('BillCountry', models.CharField(default='Indonesia', max_length=80)), + ('BillNote', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr1', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr2', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr3', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr4', models.CharField(blank=True, max_length=80, null=True)), + ('ShipAddr5', models.CharField(blank=True, max_length=80, null=True)), + ('ShipCity', models.CharField(blank=True, max_length=80, null=True)), + ('ShipState', models.CharField(blank=True, max_length=80, null=True)), + ('ShipPostalCode', models.CharField(blank=True, max_length=80, null=True)), + ('ShipCountry', models.CharField(blank=True, max_length=80, null=True)), + ('ShipNote', models.CharField(blank=True, max_length=200, null=True)), + ('PONumber', models.CharField(blank=True, max_length=30, null=True)), + ('ShipDate', models.DateTimeField(blank=True, null=True)), + ('DueDate', models.DateField(blank=True, null=True)), + ('Subtotal', models.DecimalField(decimal_places=2, max_digits=14)), + ('TotalAmount', models.DecimalField(decimal_places=2, max_digits=14)), + ('CustomerMsgRefFullName', models.CharField(blank=True, max_length=120, null=True)), + ('IsToBePrinted', models.BooleanField(default=False)), + ('IsToBeEmailed', models.BooleanField(default=False)), + ('IsManuallyClosed', models.BooleanField(default=False)), + ('IsFullyInvoiced', models.BooleanField(default=False)), + ('Memo', models.CharField(blank=True, max_length=120, null=True)), + ('NPWP', models.CharField(blank=True, max_length=20, null=True)), + ('KTP', models.CharField(blank=True, max_length=16, null=True)), + ('DMS_Cust_Name', models.CharField(blank=True, max_length=80, null=True)), + ('DMS_Cust_Code', models.CharField(blank=True, max_length=80, null=True)), + ('Special_Cust', models.BooleanField(default=False)), + ('EFaktur_Name', models.CharField(blank=True, max_length=80, null=True)), + ('Efaktur_Address', models.CharField(blank=True, max_length=80, null=True)), + ('Coordinates', models.CharField(blank=True, max_length=30, null=True)), + ('TimeCreated', models.DateTimeField(auto_now_add=True)), + ('TimeModified', models.DateTimeField(auto_now=True)), + ('CustomerRefFullName', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='Customer.customer')), + ], + ), + migrations.CreateModel( + name='SalesOrderItemLine', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('Desc', models.CharField(blank=True, max_length=80, null=True)), + ('Quantity', models.DecimalField(blank=True, decimal_places=2, max_digits=6, null=True)), + ('Rate', models.DecimalField(blank=True, decimal_places=2, max_digits=11, null=True)), + ('Amount', models.DecimalField(blank=True, decimal_places=2, max_digits=14, null=True)), + ('Invoiced', models.DecimalField(blank=True, decimal_places=2, max_digits=6, null=True)), + ('LineIsManuallyClosed', models.BooleanField(default=False)), + ('CustomerRefFullName', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='SalesOrder.salesorder')), + ('ItemRefFullName', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='Item.item')), + ('UnitOfMeasure', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='Item.uom', verbose_name='UOM')), + ], + ), + ] diff --git a/django/SalesOrder/migrations/0002_alter_salesorder_txndate.py b/django/SalesOrder/migrations/0002_alter_salesorder_txndate.py new file mode 100644 index 0000000..7956ac3 --- /dev/null +++ b/django/SalesOrder/migrations/0002_alter_salesorder_txndate.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-05-14 18:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('SalesOrder', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='salesorder', + name='TxnDate', + field=models.DateField(), + ), + ] diff --git a/django/SalesOrder/migrations/0003_rename_customerreffullname_salesorderitemline_salesorder.py b/django/SalesOrder/migrations/0003_rename_customerreffullname_salesorderitemline_salesorder.py new file mode 100644 index 0000000..000043f --- /dev/null +++ b/django/SalesOrder/migrations/0003_rename_customerreffullname_salesorderitemline_salesorder.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-05-14 19:34 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('SalesOrder', '0002_alter_salesorder_txndate'), + ] + + operations = [ + migrations.RenameField( + model_name='salesorderitemline', + old_name='CustomerRefFullName', + new_name='SalesOrder', + ), + ] diff --git a/django/SalesOrder/migrations/0004_salesorder_salesrepreffullname_and_more.py b/django/SalesOrder/migrations/0004_salesorder_salesrepreffullname_and_more.py new file mode 100644 index 0000000..c0009ab --- /dev/null +++ b/django/SalesOrder/migrations/0004_salesorder_salesrepreffullname_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2 on 2023-05-15 08:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('SalesOrder', '0003_rename_customerreffullname_salesorderitemline_salesorder'), + ] + + operations = [ + migrations.AddField( + model_name='salesorder', + name='SalesRepRefFullName', + field=models.CharField(blank=True, max_length=10, null=True), + ), + migrations.AddField( + model_name='salesorder', + name='TermsRefFullName', + field=models.CharField(blank=True, max_length=10, null=True), + ), + ] diff --git a/django/SalesOrder/migrations/0005_alter_salesorder_refnumber.py b/django/SalesOrder/migrations/0005_alter_salesorder_refnumber.py new file mode 100644 index 0000000..b3b1710 --- /dev/null +++ b/django/SalesOrder/migrations/0005_alter_salesorder_refnumber.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-05-15 08:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('SalesOrder', '0004_salesorder_salesrepreffullname_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='salesorder', + name='RefNumber', + field=models.CharField(max_length=30, verbose_name='S.O. No.'), + ), + ] diff --git a/django/SalesOrder/migrations/0006_alter_salesorder_billaddr1_alter_salesorder_ponumber_and_more.py b/django/SalesOrder/migrations/0006_alter_salesorder_billaddr1_alter_salesorder_ponumber_and_more.py new file mode 100644 index 0000000..c6d326d --- /dev/null +++ b/django/SalesOrder/migrations/0006_alter_salesorder_billaddr1_alter_salesorder_ponumber_and_more.py @@ -0,0 +1,38 @@ +# Generated by Django 4.2 on 2023-05-15 08:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('SalesOrder', '0005_alter_salesorder_refnumber'), + ] + + operations = [ + migrations.AlterField( + model_name='salesorder', + name='BillAddr1', + field=models.CharField(max_length=80, verbose_name='Name/Address'), + ), + migrations.AlterField( + model_name='salesorder', + name='PONumber', + field=models.CharField(blank=True, max_length=30, null=True, verbose_name='PO. No.'), + ), + migrations.AlterField( + model_name='salesorder', + name='SalesRepRefFullName', + field=models.CharField(blank=True, max_length=10, null=True, verbose_name='REP'), + ), + migrations.AlterField( + model_name='salesorder', + name='ShipAddr1', + field=models.CharField(blank=True, max_length=80, null=True, verbose_name='Ship To'), + ), + migrations.AlterField( + model_name='salesorder', + name='TermsRefFullName', + field=models.CharField(blank=True, max_length=10, null=True, verbose_name='Terms'), + ), + ] diff --git a/django/SalesOrder/migrations/0007_alter_salesorder_billcountry_and_more.py b/django/SalesOrder/migrations/0007_alter_salesorder_billcountry_and_more.py new file mode 100644 index 0000000..28143e1 --- /dev/null +++ b/django/SalesOrder/migrations/0007_alter_salesorder_billcountry_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2 on 2023-05-15 09:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('SalesOrder', '0006_alter_salesorder_billaddr1_alter_salesorder_ponumber_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='salesorder', + name='BillCountry', + field=models.CharField(blank=True, default='Indonesia', max_length=80, null=True), + ), + migrations.AlterField( + model_name='salesorder', + name='Subtotal', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=14, null=True), + ), + migrations.AlterField( + model_name='salesorder', + name='TotalAmount', + field=models.DecimalField(blank=True, decimal_places=2, max_digits=14, null=True), + ), + ] diff --git a/django/SalesOrder/migrations/0008_alter_salesorderitemline_lineismanuallyclosed.py b/django/SalesOrder/migrations/0008_alter_salesorderitemline_lineismanuallyclosed.py new file mode 100644 index 0000000..f5cc01b --- /dev/null +++ b/django/SalesOrder/migrations/0008_alter_salesorderitemline_lineismanuallyclosed.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2 on 2023-05-15 10:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('SalesOrder', '0007_alter_salesorder_billcountry_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='salesorderitemline', + name='LineIsManuallyClosed', + field=models.BooleanField(blank=True, default=False, null=True), + ), + ] diff --git a/django/SalesOrder/migrations/0009_remove_salesorder_subtotal.py b/django/SalesOrder/migrations/0009_remove_salesorder_subtotal.py new file mode 100644 index 0000000..a74d987 --- /dev/null +++ b/django/SalesOrder/migrations/0009_remove_salesorder_subtotal.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2 on 2023-05-19 15:33 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('SalesOrder', '0008_alter_salesorderitemline_lineismanuallyclosed'), + ] + + operations = [ + migrations.RemoveField( + model_name='salesorder', + name='Subtotal', + ), + ] diff --git a/django/SalesOrder/migrations/__init__.py b/django/SalesOrder/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django/SalesOrder/models.py b/django/SalesOrder/models.py new file mode 100644 index 0000000..c1c174c --- /dev/null +++ b/django/SalesOrder/models.py @@ -0,0 +1,135 @@ +from django.db import models +from django.urls import reverse +from Item.models import Item, UOM +from Customer.models import Customer + +class SalesOrder(models.Model): + CustomerRefFullName = models.ForeignKey(Customer, on_delete=models.PROTECT) + # TxnNumber + # ClassRefFullName + # TemplateRefFullName + TxnDate = models.DateField() + RefNumber = models.CharField(max_length=30, verbose_name="S.O. No.") + BillAddr1 = models.CharField(max_length=80, verbose_name="Name/Address") + BillAddr2 = models.CharField(max_length=80, blank=True, null=True) + BillAddr3 = models.CharField(max_length=80, blank=True, null=True) + BillAddr4 = models.CharField(max_length=80, blank=True, null=True) + BillAddr5 = models.CharField(max_length=80, blank=True, null=True) + BillCity = models.CharField(max_length=80, blank=True, null=True) + BillState = models.CharField(max_length=80, blank=True, null=True) + BillPostalCode = models.CharField(max_length=80, blank=True, null=True) + BillCountry = models.CharField(max_length=80, default="Indonesia", blank=True, null=True) + BillNote = models.CharField(max_length=80, blank=True, null=True) + # Addr1 = + # Addr2 + # Addr3 + ShipAddr1 = models.CharField(max_length=80, verbose_name="Ship To", blank=True, null=True) + ShipAddr2 = models.CharField(max_length=80, blank=True, null=True) + ShipAddr3 = models.CharField(max_length=80, blank=True, null=True) + ShipAddr4 = models.CharField(max_length=80, blank=True, null=True) + ShipAddr5 = models.CharField(max_length=80, blank=True, null=True) + ShipCity = models.CharField(max_length=80, blank=True, null=True) + ShipState = models.CharField(max_length=80, blank=True, null=True) + ShipPostalCode = models.CharField(max_length=80, blank=True, null=True) + ShipCountry = models.CharField(max_length=80, blank=True, null=True) + ShipNote = models.CharField(max_length=200, blank=True, null=True) + + # ShipAddr1 + # ShipAddr2 + # ShipAddr3 + # ShipAddr4 + # ShipCity + # ShipState + # ShipPostalCode + # ShipCountry + # City + # State + # PostalCode + # Country_Note + PONumber = models.CharField(max_length=30, verbose_name="PO. No.", blank=True, null=True) + TermsRefFullName = models.CharField(max_length=10, verbose_name="Terms", blank=True, null=True) + SalesRepRefFullName = models.CharField(max_length=10, verbose_name="REP", blank=True, null=True) + ShipDate = models.DateTimeField(blank=True, null=True) + # ShipMethodRefFullName = + DueDate = models.DateField(blank=True, null=True) + # Subtotal = models.DecimalField(max_digits=14, decimal_places=2, blank=True, null=True) + + # ItemSalesTaxRefFullName + # SalesTaxPercentage + # SalesTaxTotal + # CurrencyRefFullName + TotalAmount = models.DecimalField(max_digits=14, decimal_places=2, blank=True, null=True ) + # ExchangeRate + # TotalAmountInHomeCurrency + CustomerMsgRefFullName = models.CharField(max_length=120, blank=True, null=True) + IsToBePrinted = models.BooleanField(default=False) + IsToBeEmailed = models.BooleanField(default=False) + # CustomerSalesTaxCodeRefFullName + # Other + # FOB + IsManuallyClosed = models.BooleanField(default=False) + IsFullyInvoiced = models.BooleanField(default=False) + Memo = models.CharField(max_length=120, blank=True, null=True) + # LinkedTxnID + # TxnLineID = models.ForeignKey(SalesOrderItemLine, ondelete=models.DO_NOTHING) + + NPWP = models.CharField(max_length=20, blank=True, null=True) + KTP = models.CharField(max_length=16, blank=True, null=True) + DMS_Cust_Name = models.CharField(max_length=80, blank=True, null=True) + DMS_Cust_Code = models.CharField(max_length=80, blank=True, null=True) + Special_Cust = models.BooleanField(default=False) + EFaktur_Name = models.CharField(max_length=80, blank=True, null=True) + Efaktur_Address = models.CharField(max_length=80, blank=True, null=True) + Coordinates = models.CharField(max_length=30, blank=True, null=True) + TimeCreated = models.DateTimeField(auto_now_add=True) + TimeModified = models.DateTimeField(auto_now=True) + + def __str__(self): + return self.RefNumber + + def get_field_name(obj): + # return [(f.name, f.value_to_string(obj)) for f in obj._meta.fields] #get value convert it to string + return [(f.verbose_name, f.name, f.value_from_object(obj)) for f in obj._meta.fields] + + def get_absolute_url(self): + return reverse('SalesOrder:edit_so', args=[str(self.id)]) + + def save(self, *args, **kwargs): + + super().save(*args, **kwargs) + + +class SalesOrderItemLine(models.Model): + SalesOrder = models.ForeignKey(SalesOrder, on_delete=models.PROTECT) + ItemRefFullName = models.ForeignKey(Item, on_delete=models.PROTECT) + Desc = models.CharField(max_length=80, blank=True, null=True) + Quantity = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True) + UnitOfMeasure = models.ForeignKey(UOM, verbose_name="UOM", on_delete=models.DO_NOTHING, blank=True, null=True) + # OverrideUOMFullName + Rate = models.DecimalField(max_digits=11, decimal_places=2, blank=True, null=True) + Amount = models.DecimalField(max_digits=14, decimal_places=2, blank=True, null=True) + # InventorySiteRefFullName + # SerialNumber + # LotNumber + # SalesTaxCodeRefFullName + # Other1 + # Other2 + Invoiced = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True) #how many qty that has invoiced + LineIsManuallyClosed = models.BooleanField(default=False, blank=True, null=True) + # LineClass + # GroupTxnLineID + # GroupItemFullName + # GroupDesc + # GroupQuantity + # IsPrintItemsInGroup + # RatePercent + # GroupLineTxnLineID + # GroupLineItemFullName + # GroupLineDesc + # GroupLineQuantity + # GroupLineUOM + # GroupLineOverrideUOM + # GroupLineRate + # GroupLineAmount + # GroupLineServiceDate + # GroupLineSalesTaxCodeFullName diff --git a/django/SalesOrder/templates/SalesOrder/create-update.html b/django/SalesOrder/templates/SalesOrder/create-update.html new file mode 100644 index 0000000..0ab1d25 --- /dev/null +++ b/django/SalesOrder/templates/SalesOrder/create-update.html @@ -0,0 +1,518 @@ +{% extends 'base.html' %} +{% load crispy_forms_tags %} +{% load humanize %} +{% block title %}Sales Order{% endblock title %} + +{% block body %} + {% comment %} {% if messages %} + + {% endif %} {% endcomment %} + {% if messages %} +
    + {% for message in messages %} + {{ message }} + {% endfor %} +
+ {% endif %} + +
+
+ {% csrf_token %} +
+
{{form.CustomerRefFullName|as_crispy_field}}
+
+
+
{{form.BillAddr1|as_crispy_field}}
+
+
+
{{form.TxnDate|as_crispy_field}}
+
{{form.RefNumber|as_crispy_field}}
+
+
+ +
{{form.PONumber|as_crispy_field}}
+
+
+
{{form.SalesRepRefFullName|as_crispy_field}}
+
+ +
+
{{form.ShipAddr1|as_crispy_field}}
+
+ {{form.TotalAmount}} + + {% comment %}
{{form.IsToBePrinted.as_hidden}}
+
{{form.IsToBeEmailed.as_hidden}}
+
{{form.IsManuallyClosed.as_hidden}}
{% endcomment %} +
{{form.KTP.as_hidden}}
+
{{form.NPWP.as_hidden}}
+
{{form.DMS_Cust_Name.as_hidden}}
+
{{form.DMS_Cust_Code.as_hidden}}
+
{{form.Special_Cust.as_hidden}}
+
{{form.EFaktur_Name.as_hidden}}
+
{{form.Efaktur_Address.as_hidden}}
+
{{form.Coordinates.as_hidden}}
+
+ + + {% for hidden in form.hidden_fields %} + {{ hidden }} + {% endfor %} + + {% if formset %} + {{ formset.management_form }} +
+
ItemRefFullName*
+
Description
+
Qty
+
UOM
+
Rate
+
+
+
+ Amount
+
Del
+
+
+ +
+ {% comment %} {% for form in formset %} {% endcomment %} + {% for qs, form in qsformset %} +
+ {{form.id}} + {% comment %} {{form.ItemRefFullName.field}} {% endcomment %} +
+
+
+ {% comment %} {% endcomment %} +
+ +
+
+ +
{{form.Desc|as_crispy_field}}
+
{{form.Quantity|as_crispy_field}}
+
{{form.UnitOfMeasure|as_crispy_field}}
+
{{form.Rate|as_crispy_field}}
+ +
+
+
{{form.Amount|as_crispy_field}}
+
{{form.DELETE|as_crispy_field}}
+
+
+ {{form.Invoiced.as_hidden}} + {{form.LineIsManuallyClosed.as_hidden}} +
+
+ {% endfor %} +
+
+ + {% endif %} +
+
+ + + + {% comment %}
{% endcomment %} +
+
+ Total Amount Rp. +
+
{{form.TotalAmount.value|intcomma}} + + {% comment %} {% endcomment %} +
+ {% comment %}
{% endcomment %} +
+
+ + + +
+ + {% for item in itemdatalist %} + + + + + + + +{% endblock body %} \ No newline at end of file diff --git a/django/SalesOrder/templates/SalesOrder/index_salesorder.html b/django/SalesOrder/templates/SalesOrder/index_salesorder.html new file mode 100644 index 0000000..028a48e --- /dev/null +++ b/django/SalesOrder/templates/SalesOrder/index_salesorder.html @@ -0,0 +1 @@ +{% include 'Item/table_index.html' with title="Sales Order Index" %} \ No newline at end of file diff --git a/django/SalesOrder/templates/SalesOrder/temp.html b/django/SalesOrder/templates/SalesOrder/temp.html new file mode 100644 index 0000000..098506f --- /dev/null +++ b/django/SalesOrder/templates/SalesOrder/temp.html @@ -0,0 +1,105 @@ +{% comment %} {{form.CustomerRefFullName.errors}} + + {% if form.non_field_errors %} +
    + {% for error in form.non_field_errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %} + + {% for hidden_field in form.hidden_fields %} + {% if hidden_field.errors %} +
    + {% for error in hidden_field.errors %} +
  • (Hidden field {{ hidden_field.name }}) {{ error }}
  • + {% endfor %} +
+ {% endif %} + {{ hidden_field }} + {% endfor %} + + + {% for field in form.visible_fields %} + + + + + {% endfor %} +
{{ field.label_tag }} + {% if field.errors %} +
    + {% for error in field.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %} + {{ field }} + {% if field.help_text %} +
{{ field.help_text }} + {% endif %} +
{% endcomment %} + + + +{% comment %}
+
+
+
+
+ I'm the first element in the nested grid +
+
+ I'm the second element in the nested grid +
+
+
+
+ I'm the second element in the first grid +
+
+ I'm the third element in the first grid +
+
+
+ +
+ +
+
{{form.CustomerRefFullName|as_crispy_field}}
+ +
+
{{form.BillAddr1|as_crispy_field}}
+
+
+
{{form.TxnDate|as_crispy_field}}
+
{{form.RefNumber|as_crispy_field}}
+
+
+
{{form.CustomerRefFullName|as_crispy_field}}
+
{{form.BillAddr3|as_crispy_field}}
+
{{form.RefNumber|as_crispy_field}}
+
+
+
Outer row 1, column 3 - spans two rows (column 2 has two rows)
+
+
+ +
+
+
{{form.BillAddr1|as_crispy_field}}
+
+
+
{{form.CustomerRefFullName|as_crispy_field}}
+
{{form.CustomerRefFullName|as_crispy_field}}
+
+
+
{{form.CustomerRefFullName|as_crispy_field}}
+
{{form.CustomerRefFullName|as_crispy_field}}
+
{{form.CustomerRefFullName|as_crispy_field}}
+
+
+
Outer row 1, column 3 - spans two rows (column 2 has two rows)
+
+
+ {% endcomment %} \ No newline at end of file diff --git a/django/SalesOrder/tests.py b/django/SalesOrder/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/django/SalesOrder/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/django/SalesOrder/urls.py b/django/SalesOrder/urls.py new file mode 100644 index 0000000..d6459ec --- /dev/null +++ b/django/SalesOrder/urls.py @@ -0,0 +1,13 @@ +from django.urls import path +from . import views + +app_name = "SalesOrder" + +urlpatterns = [ + path('', views.index, name="index"), + path('add', views.add_so, name="add_so"), + path('edit/', views.add_so, name="edit_so"), + path('delete/', views.delete_so, name="delete_so"), + path('getpricelist/', views.getpricelist_so, name="getpricelist_so"), + path('getpricelist/', views.getpricelist_so, name="getpricelist"), +] \ No newline at end of file diff --git a/django/SalesOrder/views.py b/django/SalesOrder/views.py new file mode 100644 index 0000000..22be50b --- /dev/null +++ b/django/SalesOrder/views.py @@ -0,0 +1,209 @@ +from django.shortcuts import render, get_object_or_404, redirect +from django.urls import reverse +from django.http import HttpResponse, JsonResponse +from django.forms import modelformset_factory, inlineformset_factory +from django.db import transaction +from django.core import serializers +from .models import SalesOrder, SalesOrderItemLine +from Item.models import Item, PriceLevel, PriceLevelItem +from Customer.models import Customer +from .forms import SalesOrderForm, SalesOrderItemLineForm +import json +from django.core.serializers.json import DjangoJSONEncoder +from django.contrib import messages + +def index(request): + print("index SO") + context = {} + context['objects'] = SalesOrder.objects.order_by('-TimeCreated') + context['addurl'] = reverse('SalesOrder:add_so') + return render(request, "SalesOrder/index_salesorder.html", context=context) + +def add_so(request, pk=None): + print("create SO") + context = {} + obj=None + plname = None + if pk: + obj = get_object_or_404(SalesOrder.objects.select_related(), pk=pk) + # obj = get_object_or_404(SalesOrder, pk=pk) + plname = obj.CustomerRefFullName.PriceLevelRefFullName.Name + # print(f"{obj.CustomerRefFullName.PriceLevelRefFullName.Name}") + form = SalesOrderForm(request.POST or None, instance=obj) + # SalesOrderItemLineFormset = modelformset_factory(SalesOrderItemLine, form=SalesOrderItemLineForm, extra=0) #cannot use extra >0 because the formset is zip with the qs below + SalesOrderItemLineFormset = inlineformset_factory(SalesOrder, SalesOrderItemLine, form=SalesOrderItemLineForm, extra=0) #cannot use extra >0 because the formset is zip with the qs below + # SalesOrderItemLineFormset = modelformset_factory(SalesOrderItemLine, fields = ('ItemRefFullName', 'Desc', 'Quantity', 'UnitOfMeasure', 'Rate', 'Amount', 'Invoiced', 'LineIsManuallyClosed',), extra=1) + # SalesOrderItemLineFormset = modelformset_factory(SalesOrderItemLine, fields = ('ItemRefFullName', 'Desc', 'Quantity', 'UnitOfMeasure', 'Rate', 'Amount', 'Invoiced', 'LineIsManuallyClosed',), extra=1) + qs=None + formset = SalesOrderItemLineFormset(request.POST or None) + if pk: + print("got ID") + qs = obj.salesorderitemline_set.all().order_by('id').select_related('ItemRefFullName') + # formset = SalesOrderItemLineFormset(request.POST or None, queryset=qs) + formset = SalesOrderItemLineFormset(request.POST or None, instance=obj) + print(request.POST) + # print(formset) + # print(len(formset)) + # print(f"queryset={qs}") + # print(f"queryset={qs[0].ItemRefFullName}") + # qsItemList = list(x.ItemRefFullName for x in qs) + # print(qsItemList) + print(f'plname:{plname}') + qsIn = Item.objects.filter(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values('id', 'FullName','SalesDesc', 'SalesPrice', 'itempricelevel__Price') + qsEx = Item.objects.exclude(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values( "id", "FullName", "SalesDesc", "SalesPrice", "AlwaysNull") + # print(qsIn) + # print("qsEx") + # print(qsEx) + context['itemdatalist'] = qsIn.union(qsEx) + + context['object'] = obj + context['qsformset'] = None + if pk: + context['qsformset'] = list(zip(qs, formset)) + if request.method == "POST": + with transaction.atomic(): + if form.is_valid(): + # print(form.cleaned_data) + # with transaction.atomic(): + # print(formset) + if formset.is_valid(): + for delform in formset.deleted_forms: + pass + totalamount=form.cleaned_data['TotalAmount'] + print(totalamount, type(totalamount)) + totalamountChildren=0 + for fm in formset: + # print(fm) + print(fm['DELETE'].value()) + if not fm['DELETE'].value() and 'Amount' in fm.cleaned_data: + print(f"fm.cleaced_data: {fm.cleaned_data['Amount']}") + amount=fm.cleaned_data['Amount'] + # print(amount) + print(fm['DELETE'].value()) + totalamountChildren+=amount + print(totalamountChildren) + if totalamount==totalamountChildren: + print("correct total amount") + else: + print(f"not correct total amount:{totalamount} supposed={totalamountChildren}") + # form.cleaned_data['TotalAmount'] = totalamountChildren + parentobj = form.save(commit=False) + parentobj.TotalAmount = totalamountChildren + parentobj.save() + # print(parentobj) + print("formset valid") + instances = formset.save(commit=False) + for obj in formset.deleted_objects: + print("deelted object") + print(obj) + obj.delete() + for instance in instances: + # print(instance.ItemRefFullName) + # print(instance.pk) + # print(parentobj.id) + instance.SalesOrder = parentobj + instance.save() + context['message'] = "All Data Saved" + print("all formset saved") + print(parentobj.pk, type(parentobj.pk)) + print(reverse('SalesOrder:edit_so', args=[parentobj.pk])) + messages.success(request, "All Data is Saved") + return redirect(reverse('SalesOrder:edit_so', args=[parentobj.pk])) + else: + print("formset error") + print(formset.errors) + else: + print("form error") + print(form.errors) + context['form'] = form + context['formset'] = formset + return render(request, "SalesOrder/create-update.html", context=context) + +# def add_so(request): +# print("create SO") +# context = {} +# # obj = get_object_or_404(SalesOrder, pk=id) +# obj=None +# form = SalesOrderForm(request.POST or None, ) +# SalesOrderItemLineFormset = modelformset_factory(SalesOrderItemLine, form=SalesOrderItemLineForm, extra=1) +# # qs = obj.salesorderitemline_set.all() +# qs=None +# formset = SalesOrderItemLineFormset(request.POST or None, ) +# context['form'] = form +# context['formset'] = formset +# context['object'] = obj + +# if all([form.is_valid(), formset.is_valid()]): +# print(form.cleaned_data) +# for form in formset: +# print(form.clean_data) +# context['message'] = "All Data saved" +# return render(request, "SalesOrder/create-update.html", context=context) + + +def getpricelist_so(request, pk=None): + print(f"getpricelist SO; pk={pk}") + context = {} + obj=None + plname = None + if pk: + # obj = get_object_or_404(SalesOrder.objects.select_related(), pk=pk) + obj = get_object_or_404(Customer.objects.select_related(), pk=pk) + plname = obj.PriceLevelRefFullName.Name + # print(f"{obj.CustomerRefFullName.PriceLevelRefFullName.Name}") + # form = SalesOrderForm(request.POST or None, instance=obj) + # SalesOrderItemLineFormset = inlineformset_factory(SalesOrder, SalesOrderItemLine, form=SalesOrderItemLineForm, extra=0) #cannot use extra >0 because the formset is zip with the qs below + print(obj) + qs=None + # formset = SalesOrderItemLineFormset(request.POST or None) + # if pk: + # print("got ID") + # qs = obj.salesorderitemline_set.all().order_by('id').select_related('ItemRefFullName') + # # formset = SalesOrderItemLineFormset(request.POST or None, queryset=qs) + # formset = SalesOrderItemLineFormset(request.POST or None, instance=obj) + print(request.GET) + # print(len(formset)) + # print(f"queryset={qs}") + # print(f"queryset={qs[0].ItemRefFullName}") + # qsItemList = list(x.ItemRefFullName for x in qs) + # print(qsItemList) + print(f'plname:{plname}') + qsIn = Item.objects.filter(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values('id', 'FullName','SalesDesc', 'SalesPrice', 'itempricelevel__Price') + qsEx = Item.objects.exclude(itempricelevel__PL__Name=plname).prefetch_related("itempricelevel").values( "id", "FullName", "SalesDesc", "SalesPrice", "AlwaysNull") + context['itemdatalist'] = qsIn.union(qsEx) + serialized_q = json.dumps(list( context['itemdatalist']), cls=DjangoJSONEncoder) + # p=json.loads(serialized_q) + # print(serialized_q) + serialized_obj = serializers.serialize('json', [ obj, ]) + context['obj'] = serialized_obj + context['itemdatalist'] = serialized_q + # serialized_q = serialized_q + serialized_obj + # print(serialized_obj) + data = json.dumps(context, indent=4, sort_keys=True, default=str) + # print(data) + # print(serialized_q) + return JsonResponse(data, safe=False) + +def edit_so(request): + print("Edit SO") + context = {} + obj = get_object_or_404(SalesOrder, pk=id) + form = SalesOrderForm(request.POST or None, instance=obj) + SalesOrderItemLineFormset = modelformset_factory(SalesOrderItemLine, form=SalesOrderItemLineForm, extra=1) + qs = obj.salesorderitemline_set.all() + formset = SalesOrderItemLineFormset(request.POST or None, isinstance=qs) + context['form'] = form + context['formset'] = formset + context['object'] = obj + + if all([form.is_valid(), formset.is_valid()]): + print(form.cleaned_data) + for form in formset: + print(form.clean_data) + context['message'] = "All Data saved" + return render(request, "SalesOrder/create-update.html", context=context) + +def delete_so(request): + pass + + diff --git a/django/__init__.py b/django/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django/manage.py b/django/manage.py new file mode 100644 index 0000000..feea57b --- /dev/null +++ b/django/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Inventory.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/django/requirements.txt b/django/requirements.txt new file mode 100644 index 0000000..e80b5c1 Binary files /dev/null and b/django/requirements.txt differ diff --git a/django/static/bootstrap.bundle.min.js b/django/static/bootstrap.bundle.min.js new file mode 100644 index 0000000..819659b --- /dev/null +++ b/django/static/bootstrap.bundle.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v5.2.3 (https://getbootstrap.com/) + * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";const t="transitionend",e=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return e},i=t=>{const i=e(t);return i&&document.querySelector(i)?i:null},n=t=>{const i=e(t);return i?document.querySelector(i):null},s=e=>{e.dispatchEvent(new Event(t))},o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(t):null,a=t=>{if(!o(t)||0===t.getClientRects().length)return!1;const e="visible"===getComputedStyle(t).getPropertyValue("visibility"),i=t.closest("details:not([open])");if(!i)return e;if(i!==t){const e=t.closest("summary");if(e&&e.parentNode!==i)return!1;if(null===e)return!1}return e},l=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),c=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?c(t.parentNode):null},h=()=>{},d=t=>{t.offsetHeight},u=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,f=[],p=()=>"rtl"===document.documentElement.dir,g=t=>{var e;e=()=>{const e=u();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(f.length||document.addEventListener("DOMContentLoaded",(()=>{for(const t of f)t()})),f.push(e)):e()},m=t=>{"function"==typeof t&&t()},_=(e,i,n=!0)=>{if(!n)return void m(e);const o=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(i)+5;let r=!1;const a=({target:n})=>{n===i&&(r=!0,i.removeEventListener(t,a),m(e))};i.addEventListener(t,a),setTimeout((()=>{r||s(i)}),o)},b=(t,e,i,n)=>{const s=t.length;let o=t.indexOf(e);return-1===o?!i&&n?t[s-1]:t[0]:(o+=i?1:-1,n&&(o=(o+s)%s),t[Math.max(0,Math.min(o,s-1))])},v=/[^.]*(?=\..*)\.|.*/,y=/\..*/,w=/::\d+$/,A={};let E=1;const T={mouseenter:"mouseover",mouseleave:"mouseout"},C=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function O(t,e){return e&&`${e}::${E++}`||t.uidEvent||E++}function x(t){const e=O(t);return t.uidEvent=e,A[e]=A[e]||{},A[e]}function k(t,e,i=null){return Object.values(t).find((t=>t.callable===e&&t.delegationSelector===i))}function L(t,e,i){const n="string"==typeof e,s=n?i:e||i;let o=N(t);return C.has(o)||(o=t),[n,s,o]}function D(t,e,i,n,s){if("string"!=typeof e||!t)return;let[o,r,a]=L(e,i,n);if(e in T){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};r=t(r)}const l=x(t),c=l[a]||(l[a]={}),h=k(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=O(r,e.replace(v,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(const a of o)if(a===r)return j(s,{delegateTarget:r}),n.oneOff&&P.off(t,s.type,e,i),i.apply(r,[s])}}(t,i,r):function(t,e){return function i(n){return j(n,{delegateTarget:t}),i.oneOff&&P.off(t,n.type,e),e.apply(t,[n])}}(t,r);u.delegationSelector=o?i:null,u.callable=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function S(t,e,i,n,s){const o=k(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function I(t,e,i,n){const s=e[i]||{};for(const o of Object.keys(s))if(o.includes(n)){const n=s[o];S(t,e,i,n.callable,n.delegationSelector)}}function N(t){return t=t.replace(y,""),T[t]||t}const P={on(t,e,i,n){D(t,e,i,n,!1)},one(t,e,i,n){D(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=L(e,i,n),a=r!==e,l=x(t),c=l[r]||{},h=e.startsWith(".");if(void 0===o){if(h)for(const i of Object.keys(l))I(t,l,i,e.slice(1));for(const i of Object.keys(c)){const n=i.replace(w,"");if(!a||e.includes(n)){const e=c[i];S(t,l,r,e.callable,e.delegationSelector)}}}else{if(!Object.keys(c).length)return;S(t,l,r,o,s?i:null)}},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=u();let s=null,o=!0,r=!0,a=!1;e!==N(e)&&n&&(s=n.Event(e,i),n(t).trigger(s),o=!s.isPropagationStopped(),r=!s.isImmediatePropagationStopped(),a=s.isDefaultPrevented());let l=new Event(e,{bubbles:o,cancelable:!0});return l=j(l,i),a&&l.preventDefault(),r&&t.dispatchEvent(l),l.defaultPrevented&&s&&s.preventDefault(),l}};function j(t,e){for(const[i,n]of Object.entries(e||{}))try{t[i]=n}catch(e){Object.defineProperty(t,i,{configurable:!0,get:()=>n})}return t}const M=new Map,H={set(t,e,i){M.has(t)||M.set(t,new Map);const n=M.get(t);n.has(e)||0===n.size?n.set(e,i):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(n.keys())[0]}.`)},get:(t,e)=>M.has(t)&&M.get(t).get(e)||null,remove(t,e){if(!M.has(t))return;const i=M.get(t);i.delete(e),0===i.size&&M.delete(t)}};function $(t){if("true"===t)return!0;if("false"===t)return!1;if(t===Number(t).toString())return Number(t);if(""===t||"null"===t)return null;if("string"!=typeof t)return t;try{return JSON.parse(decodeURIComponent(t))}catch(e){return t}}function W(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}const B={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${W(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${W(e)}`)},getDataAttributes(t){if(!t)return{};const e={},i=Object.keys(t.dataset).filter((t=>t.startsWith("bs")&&!t.startsWith("bsConfig")));for(const n of i){let i=n.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1,i.length),e[i]=$(t.dataset[n])}return e},getDataAttribute:(t,e)=>$(t.getAttribute(`data-bs-${W(e)}`))};class F{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(t){return t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t}_mergeConfigObj(t,e){const i=o(e)?B.getDataAttribute(e,"config"):{};return{...this.constructor.Default,..."object"==typeof i?i:{},...o(e)?B.getDataAttributes(e):{},..."object"==typeof t?t:{}}}_typeCheckConfig(t,e=this.constructor.DefaultType){for(const n of Object.keys(e)){const s=e[n],r=t[n],a=o(r)?"element":null==(i=r)?`${i}`:Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(s).test(a))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${n}" provided type "${a}" but expected type "${s}".`)}var i}}class z extends F{constructor(t,e){super(),(t=r(t))&&(this._element=t,this._config=this._getConfig(e),H.set(this._element,this.constructor.DATA_KEY,this))}dispose(){H.remove(this._element,this.constructor.DATA_KEY),P.off(this._element,this.constructor.EVENT_KEY);for(const t of Object.getOwnPropertyNames(this))this[t]=null}_queueCallback(t,e,i=!0){_(t,e,i)}_getConfig(t){return t=this._mergeConfigObj(t,this._element),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}static getInstance(t){return H.get(r(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.2.3"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(t){return`${t}${this.EVENT_KEY}`}}const q=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,s=t.NAME;P.on(document,i,`[data-bs-dismiss="${s}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),l(this))return;const o=n(this)||this.closest(`.${s}`);t.getOrCreateInstance(o)[e]()}))};class R extends z{static get NAME(){return"alert"}close(){if(P.trigger(this._element,"close.bs.alert").defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),P.trigger(this._element,"closed.bs.alert"),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=R.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}q(R,"close"),g(R);const V='[data-bs-toggle="button"]';class K extends z{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=K.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}P.on(document,"click.bs.button.data-api",V,(t=>{t.preventDefault();const e=t.target.closest(V);K.getOrCreateInstance(e).toggle()})),g(K);const Q={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode.closest(e);for(;n;)i.push(n),n=n.parentNode.closest(e);return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(",");return this.find(e,t).filter((t=>!l(t)&&a(t)))}},X={endCallback:null,leftCallback:null,rightCallback:null},Y={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class U extends F{constructor(t,e){super(),this._element=t,t&&U.isSupported()&&(this._config=this._getConfig(e),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents())}static get Default(){return X}static get DefaultType(){return Y}static get NAME(){return"swipe"}dispose(){P.off(this._element,".bs.swipe")}_start(t){this._supportPointerEvents?this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX):this._deltaX=t.touches[0].clientX}_end(t){this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX-this._deltaX),this._handleSwipe(),m(this._config.endCallback)}_move(t){this._deltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this._deltaX}_handleSwipe(){const t=Math.abs(this._deltaX);if(t<=40)return;const e=t/this._deltaX;this._deltaX=0,e&&m(e>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(P.on(this._element,"pointerdown.bs.swipe",(t=>this._start(t))),P.on(this._element,"pointerup.bs.swipe",(t=>this._end(t))),this._element.classList.add("pointer-event")):(P.on(this._element,"touchstart.bs.swipe",(t=>this._start(t))),P.on(this._element,"touchmove.bs.swipe",(t=>this._move(t))),P.on(this._element,"touchend.bs.swipe",(t=>this._end(t))))}_eventIsPointerPenTouch(t){return this._supportPointerEvents&&("pen"===t.pointerType||"touch"===t.pointerType)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const G="next",J="prev",Z="left",tt="right",et="slid.bs.carousel",it="carousel",nt="active",st={ArrowLeft:tt,ArrowRight:Z},ot={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},rt={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class at extends z{constructor(t,e){super(t,e),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=Q.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===it&&this.cycle()}static get Default(){return ot}static get DefaultType(){return rt}static get NAME(){return"carousel"}next(){this._slide(G)}nextWhenVisible(){!document.hidden&&a(this._element)&&this.next()}prev(){this._slide(J)}pause(){this._isSliding&&s(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval((()=>this.nextWhenVisible()),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?P.one(this._element,et,(()=>this.cycle())):this.cycle())}to(t){const e=this._getItems();if(t>e.length-1||t<0)return;if(this._isSliding)return void P.one(this._element,et,(()=>this.to(t)));const i=this._getItemIndex(this._getActive());if(i===t)return;const n=t>i?G:J;this._slide(n,e[t])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(t){return t.defaultInterval=t.interval,t}_addEventListeners(){this._config.keyboard&&P.on(this._element,"keydown.bs.carousel",(t=>this._keydown(t))),"hover"===this._config.pause&&(P.on(this._element,"mouseenter.bs.carousel",(()=>this.pause())),P.on(this._element,"mouseleave.bs.carousel",(()=>this._maybeEnableCycle()))),this._config.touch&&U.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const t of Q.find(".carousel-item img",this._element))P.on(t,"dragstart.bs.carousel",(t=>t.preventDefault()));const t={leftCallback:()=>this._slide(this._directionToOrder(Z)),rightCallback:()=>this._slide(this._directionToOrder(tt)),endCallback:()=>{"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((()=>this._maybeEnableCycle()),500+this._config.interval))}};this._swipeHelper=new U(this._element,t)}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=st[t.key];e&&(t.preventDefault(),this._slide(this._directionToOrder(e)))}_getItemIndex(t){return this._getItems().indexOf(t)}_setActiveIndicatorElement(t){if(!this._indicatorsElement)return;const e=Q.findOne(".active",this._indicatorsElement);e.classList.remove(nt),e.removeAttribute("aria-current");const i=Q.findOne(`[data-bs-slide-to="${t}"]`,this._indicatorsElement);i&&(i.classList.add(nt),i.setAttribute("aria-current","true"))}_updateInterval(){const t=this._activeElement||this._getActive();if(!t)return;const e=Number.parseInt(t.getAttribute("data-bs-interval"),10);this._config.interval=e||this._config.defaultInterval}_slide(t,e=null){if(this._isSliding)return;const i=this._getActive(),n=t===G,s=e||b(this._getItems(),i,n,this._config.wrap);if(s===i)return;const o=this._getItemIndex(s),r=e=>P.trigger(this._element,e,{relatedTarget:s,direction:this._orderToDirection(t),from:this._getItemIndex(i),to:o});if(r("slide.bs.carousel").defaultPrevented)return;if(!i||!s)return;const a=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(o),this._activeElement=s;const l=n?"carousel-item-start":"carousel-item-end",c=n?"carousel-item-next":"carousel-item-prev";s.classList.add(c),d(s),i.classList.add(l),s.classList.add(l),this._queueCallback((()=>{s.classList.remove(l,c),s.classList.add(nt),i.classList.remove(nt,c,l),this._isSliding=!1,r(et)}),i,this._isAnimated()),a&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return Q.findOne(".active.carousel-item",this._element)}_getItems(){return Q.find(".carousel-item",this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(t){return p()?t===Z?J:G:t===Z?G:J}_orderToDirection(t){return p()?t===J?Z:tt:t===J?tt:Z}static jQueryInterface(t){return this.each((function(){const e=at.getOrCreateInstance(this,t);if("number"!=typeof t){if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}else e.to(t)}))}}P.on(document,"click.bs.carousel.data-api","[data-bs-slide], [data-bs-slide-to]",(function(t){const e=n(this);if(!e||!e.classList.contains(it))return;t.preventDefault();const i=at.getOrCreateInstance(e),s=this.getAttribute("data-bs-slide-to");return s?(i.to(s),void i._maybeEnableCycle()):"next"===B.getDataAttribute(this,"slide")?(i.next(),void i._maybeEnableCycle()):(i.prev(),void i._maybeEnableCycle())})),P.on(window,"load.bs.carousel.data-api",(()=>{const t=Q.find('[data-bs-ride="carousel"]');for(const e of t)at.getOrCreateInstance(e)})),g(at);const lt="show",ct="collapse",ht="collapsing",dt='[data-bs-toggle="collapse"]',ut={parent:null,toggle:!0},ft={parent:"(null|element)",toggle:"boolean"};class pt extends z{constructor(t,e){super(t,e),this._isTransitioning=!1,this._triggerArray=[];const n=Q.find(dt);for(const t of n){const e=i(t),n=Q.find(e).filter((t=>t===this._element));null!==e&&n.length&&this._triggerArray.push(t)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return ut}static get DefaultType(){return ft}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t=[];if(this._config.parent&&(t=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((t=>t!==this._element)).map((t=>pt.getOrCreateInstance(t,{toggle:!1})))),t.length&&t[0]._isTransitioning)return;if(P.trigger(this._element,"show.bs.collapse").defaultPrevented)return;for(const e of t)e.hide();const e=this._getDimension();this._element.classList.remove(ct),this._element.classList.add(ht),this._element.style[e]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const i=`scroll${e[0].toUpperCase()+e.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(ht),this._element.classList.add(ct,lt),this._element.style[e]="",P.trigger(this._element,"shown.bs.collapse")}),this._element,!0),this._element.style[e]=`${this._element[i]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(P.trigger(this._element,"hide.bs.collapse").defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,d(this._element),this._element.classList.add(ht),this._element.classList.remove(ct,lt);for(const t of this._triggerArray){const e=n(t);e&&!this._isShown(e)&&this._addAriaAndCollapsedClass([t],!1)}this._isTransitioning=!0,this._element.style[t]="",this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(ht),this._element.classList.add(ct),P.trigger(this._element,"hidden.bs.collapse")}),this._element,!0)}_isShown(t=this._element){return t.classList.contains(lt)}_configAfterMerge(t){return t.toggle=Boolean(t.toggle),t.parent=r(t.parent),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=this._getFirstLevelChildren(dt);for(const e of t){const t=n(e);t&&this._addAriaAndCollapsedClass([e],this._isShown(t))}}_getFirstLevelChildren(t){const e=Q.find(":scope .collapse .collapse",this._config.parent);return Q.find(t,this._config.parent).filter((t=>!e.includes(t)))}_addAriaAndCollapsedClass(t,e){if(t.length)for(const i of t)i.classList.toggle("collapsed",!e),i.setAttribute("aria-expanded",e)}static jQueryInterface(t){const e={};return"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1),this.each((function(){const i=pt.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}P.on(document,"click.bs.collapse.data-api",dt,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();const e=i(this),n=Q.find(e);for(const t of n)pt.getOrCreateInstance(t,{toggle:!1}).toggle()})),g(pt);var gt="top",mt="bottom",_t="right",bt="left",vt="auto",yt=[gt,mt,_t,bt],wt="start",At="end",Et="clippingParents",Tt="viewport",Ct="popper",Ot="reference",xt=yt.reduce((function(t,e){return t.concat([e+"-"+wt,e+"-"+At])}),[]),kt=[].concat(yt,[vt]).reduce((function(t,e){return t.concat([e,e+"-"+wt,e+"-"+At])}),[]),Lt="beforeRead",Dt="read",St="afterRead",It="beforeMain",Nt="main",Pt="afterMain",jt="beforeWrite",Mt="write",Ht="afterWrite",$t=[Lt,Dt,St,It,Nt,Pt,jt,Mt,Ht];function Wt(t){return t?(t.nodeName||"").toLowerCase():null}function Bt(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function Ft(t){return t instanceof Bt(t).Element||t instanceof Element}function zt(t){return t instanceof Bt(t).HTMLElement||t instanceof HTMLElement}function qt(t){return"undefined"!=typeof ShadowRoot&&(t instanceof Bt(t).ShadowRoot||t instanceof ShadowRoot)}const Rt={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];zt(s)&&Wt(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});zt(n)&&Wt(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}},requires:["computeStyles"]};function Vt(t){return t.split("-")[0]}var Kt=Math.max,Qt=Math.min,Xt=Math.round;function Yt(){var t=navigator.userAgentData;return null!=t&&t.brands?t.brands.map((function(t){return t.brand+"/"+t.version})).join(" "):navigator.userAgent}function Ut(){return!/^((?!chrome|android).)*safari/i.test(Yt())}function Gt(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1);var n=t.getBoundingClientRect(),s=1,o=1;e&&zt(t)&&(s=t.offsetWidth>0&&Xt(n.width)/t.offsetWidth||1,o=t.offsetHeight>0&&Xt(n.height)/t.offsetHeight||1);var r=(Ft(t)?Bt(t):window).visualViewport,a=!Ut()&&i,l=(n.left+(a&&r?r.offsetLeft:0))/s,c=(n.top+(a&&r?r.offsetTop:0))/o,h=n.width/s,d=n.height/o;return{width:h,height:d,top:c,right:l+h,bottom:c+d,left:l,x:l,y:c}}function Jt(t){var e=Gt(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function Zt(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&qt(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function te(t){return Bt(t).getComputedStyle(t)}function ee(t){return["table","td","th"].indexOf(Wt(t))>=0}function ie(t){return((Ft(t)?t.ownerDocument:t.document)||window.document).documentElement}function ne(t){return"html"===Wt(t)?t:t.assignedSlot||t.parentNode||(qt(t)?t.host:null)||ie(t)}function se(t){return zt(t)&&"fixed"!==te(t).position?t.offsetParent:null}function oe(t){for(var e=Bt(t),i=se(t);i&&ee(i)&&"static"===te(i).position;)i=se(i);return i&&("html"===Wt(i)||"body"===Wt(i)&&"static"===te(i).position)?e:i||function(t){var e=/firefox/i.test(Yt());if(/Trident/i.test(Yt())&&zt(t)&&"fixed"===te(t).position)return null;var i=ne(t);for(qt(i)&&(i=i.host);zt(i)&&["html","body"].indexOf(Wt(i))<0;){var n=te(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function re(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function ae(t,e,i){return Kt(t,Qt(e,i))}function le(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function ce(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}const he={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=Vt(i.placement),l=re(a),c=[bt,_t].indexOf(a)>=0?"height":"width";if(o&&r){var h=function(t,e){return le("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:ce(t,yt))}(s.padding,i),d=Jt(o),u="y"===l?gt:bt,f="y"===l?mt:_t,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],g=r[l]-i.rects.reference[l],m=oe(o),_=m?"y"===l?m.clientHeight||0:m.clientWidth||0:0,b=p/2-g/2,v=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+b,A=ae(v,w,y),E=l;i.modifiersData[n]=((e={})[E]=A,e.centerOffset=A-w,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&Zt(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function de(t){return t.split("-")[1]}var ue={top:"auto",right:"auto",bottom:"auto",left:"auto"};function fe(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=t.isFixed,u=r.x,f=void 0===u?0:u,p=r.y,g=void 0===p?0:p,m="function"==typeof h?h({x:f,y:g}):{x:f,y:g};f=m.x,g=m.y;var _=r.hasOwnProperty("x"),b=r.hasOwnProperty("y"),v=bt,y=gt,w=window;if(c){var A=oe(i),E="clientHeight",T="clientWidth";A===Bt(i)&&"static"!==te(A=ie(i)).position&&"absolute"===a&&(E="scrollHeight",T="scrollWidth"),(s===gt||(s===bt||s===_t)&&o===At)&&(y=mt,g-=(d&&A===w&&w.visualViewport?w.visualViewport.height:A[E])-n.height,g*=l?1:-1),s!==bt&&(s!==gt&&s!==mt||o!==At)||(v=_t,f-=(d&&A===w&&w.visualViewport?w.visualViewport.width:A[T])-n.width,f*=l?1:-1)}var C,O=Object.assign({position:a},c&&ue),x=!0===h?function(t){var e=t.x,i=t.y,n=window.devicePixelRatio||1;return{x:Xt(e*n)/n||0,y:Xt(i*n)/n||0}}({x:f,y:g}):{x:f,y:g};return f=x.x,g=x.y,l?Object.assign({},O,((C={})[y]=b?"0":"",C[v]=_?"0":"",C.transform=(w.devicePixelRatio||1)<=1?"translate("+f+"px, "+g+"px)":"translate3d("+f+"px, "+g+"px, 0)",C)):Object.assign({},O,((e={})[y]=b?g+"px":"",e[v]=_?f+"px":"",e.transform="",e))}const pe={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:Vt(e.placement),variation:de(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s,isFixed:"fixed"===e.options.strategy};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,fe(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,fe(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var ge={passive:!0};const me={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=Bt(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,ge)})),a&&l.addEventListener("resize",i.update,ge),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,ge)})),a&&l.removeEventListener("resize",i.update,ge)}},data:{}};var _e={left:"right",right:"left",bottom:"top",top:"bottom"};function be(t){return t.replace(/left|right|bottom|top/g,(function(t){return _e[t]}))}var ve={start:"end",end:"start"};function ye(t){return t.replace(/start|end/g,(function(t){return ve[t]}))}function we(t){var e=Bt(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function Ae(t){return Gt(ie(t)).left+we(t).scrollLeft}function Ee(t){var e=te(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function Te(t){return["html","body","#document"].indexOf(Wt(t))>=0?t.ownerDocument.body:zt(t)&&Ee(t)?t:Te(ne(t))}function Ce(t,e){var i;void 0===e&&(e=[]);var n=Te(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=Bt(n),r=s?[o].concat(o.visualViewport||[],Ee(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(Ce(ne(r)))}function Oe(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function xe(t,e,i){return e===Tt?Oe(function(t,e){var i=Bt(t),n=ie(t),s=i.visualViewport,o=n.clientWidth,r=n.clientHeight,a=0,l=0;if(s){o=s.width,r=s.height;var c=Ut();(c||!c&&"fixed"===e)&&(a=s.offsetLeft,l=s.offsetTop)}return{width:o,height:r,x:a+Ae(t),y:l}}(t,i)):Ft(e)?function(t,e){var i=Gt(t,!1,"fixed"===e);return i.top=i.top+t.clientTop,i.left=i.left+t.clientLeft,i.bottom=i.top+t.clientHeight,i.right=i.left+t.clientWidth,i.width=t.clientWidth,i.height=t.clientHeight,i.x=i.left,i.y=i.top,i}(e,i):Oe(function(t){var e,i=ie(t),n=we(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=Kt(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=Kt(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+Ae(t),l=-n.scrollTop;return"rtl"===te(s||i).direction&&(a+=Kt(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(ie(t)))}function ke(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?Vt(s):null,r=s?de(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;switch(o){case gt:e={x:a,y:i.y-n.height};break;case mt:e={x:a,y:i.y+i.height};break;case _t:e={x:i.x+i.width,y:l};break;case bt:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?re(o):null;if(null!=c){var h="y"===c?"height":"width";switch(r){case wt:e[c]=e[c]-(i[h]/2-n[h]/2);break;case At:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function Le(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.strategy,r=void 0===o?t.strategy:o,a=i.boundary,l=void 0===a?Et:a,c=i.rootBoundary,h=void 0===c?Tt:c,d=i.elementContext,u=void 0===d?Ct:d,f=i.altBoundary,p=void 0!==f&&f,g=i.padding,m=void 0===g?0:g,_=le("number"!=typeof m?m:ce(m,yt)),b=u===Ct?Ot:Ct,v=t.rects.popper,y=t.elements[p?b:u],w=function(t,e,i,n){var s="clippingParents"===e?function(t){var e=Ce(ne(t)),i=["absolute","fixed"].indexOf(te(t).position)>=0&&zt(t)?oe(t):t;return Ft(i)?e.filter((function(t){return Ft(t)&&Zt(t,i)&&"body"!==Wt(t)})):[]}(t):[].concat(e),o=[].concat(s,[i]),r=o[0],a=o.reduce((function(e,i){var s=xe(t,i,n);return e.top=Kt(s.top,e.top),e.right=Qt(s.right,e.right),e.bottom=Qt(s.bottom,e.bottom),e.left=Kt(s.left,e.left),e}),xe(t,r,n));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}(Ft(y)?y:y.contextElement||ie(t.elements.popper),l,h,r),A=Gt(t.elements.reference),E=ke({reference:A,element:v,strategy:"absolute",placement:s}),T=Oe(Object.assign({},v,E)),C=u===Ct?T:A,O={top:w.top-C.top+_.top,bottom:C.bottom-w.bottom+_.bottom,left:w.left-C.left+_.left,right:C.right-w.right+_.right},x=t.modifiersData.offset;if(u===Ct&&x){var k=x[s];Object.keys(O).forEach((function(t){var e=[_t,mt].indexOf(t)>=0?1:-1,i=[gt,mt].indexOf(t)>=0?"y":"x";O[t]+=k[i]*e}))}return O}function De(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?kt:l,h=de(n),d=h?a?xt:xt.filter((function(t){return de(t)===h})):yt,u=d.filter((function(t){return c.indexOf(t)>=0}));0===u.length&&(u=d);var f=u.reduce((function(e,i){return e[i]=Le(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[Vt(i)],e}),{});return Object.keys(f).sort((function(t,e){return f[t]-f[e]}))}const Se={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,g=i.allowedAutoPlacements,m=e.options.placement,_=Vt(m),b=l||(_!==m&&p?function(t){if(Vt(t)===vt)return[];var e=be(t);return[ye(t),e,ye(e)]}(m):[be(m)]),v=[m].concat(b).reduce((function(t,i){return t.concat(Vt(i)===vt?De(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:g}):i)}),[]),y=e.rects.reference,w=e.rects.popper,A=new Map,E=!0,T=v[0],C=0;C=0,D=L?"width":"height",S=Le(e,{placement:O,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),I=L?k?_t:bt:k?mt:gt;y[D]>w[D]&&(I=be(I));var N=be(I),P=[];if(o&&P.push(S[x]<=0),a&&P.push(S[I]<=0,S[N]<=0),P.every((function(t){return t}))){T=O,E=!1;break}A.set(O,P)}if(E)for(var j=function(t){var e=v.find((function(e){var i=A.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return T=e,"break"},M=p?3:1;M>0&&"break"!==j(M);M--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function Ie(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function Ne(t){return[gt,_t,mt,bt].some((function(e){return t[e]>=0}))}const Pe={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=Le(e,{elementContext:"reference"}),a=Le(e,{altBoundary:!0}),l=Ie(r,n),c=Ie(a,s,o),h=Ne(l),d=Ne(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},je={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=kt.reduce((function(t,i){return t[i]=function(t,e,i){var n=Vt(t),s=[bt,gt].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[bt,_t].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t}),{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}},Me={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=ke({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},He={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,g=void 0===p?0:p,m=Le(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=Vt(e.placement),b=de(e.placement),v=!b,y=re(_),w="x"===y?"y":"x",A=e.modifiersData.popperOffsets,E=e.rects.reference,T=e.rects.popper,C="function"==typeof g?g(Object.assign({},e.rects,{placement:e.placement})):g,O="number"==typeof C?{mainAxis:C,altAxis:C}:Object.assign({mainAxis:0,altAxis:0},C),x=e.modifiersData.offset?e.modifiersData.offset[e.placement]:null,k={x:0,y:0};if(A){if(o){var L,D="y"===y?gt:bt,S="y"===y?mt:_t,I="y"===y?"height":"width",N=A[y],P=N+m[D],j=N-m[S],M=f?-T[I]/2:0,H=b===wt?E[I]:T[I],$=b===wt?-T[I]:-E[I],W=e.elements.arrow,B=f&&W?Jt(W):{width:0,height:0},F=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},z=F[D],q=F[S],R=ae(0,E[I],B[I]),V=v?E[I]/2-M-R-z-O.mainAxis:H-R-z-O.mainAxis,K=v?-E[I]/2+M+R+q+O.mainAxis:$+R+q+O.mainAxis,Q=e.elements.arrow&&oe(e.elements.arrow),X=Q?"y"===y?Q.clientTop||0:Q.clientLeft||0:0,Y=null!=(L=null==x?void 0:x[y])?L:0,U=N+K-Y,G=ae(f?Qt(P,N+V-Y-X):P,N,f?Kt(j,U):j);A[y]=G,k[y]=G-N}if(a){var J,Z="x"===y?gt:bt,tt="x"===y?mt:_t,et=A[w],it="y"===w?"height":"width",nt=et+m[Z],st=et-m[tt],ot=-1!==[gt,bt].indexOf(_),rt=null!=(J=null==x?void 0:x[w])?J:0,at=ot?nt:et-E[it]-T[it]-rt+O.altAxis,lt=ot?et+E[it]+T[it]-rt-O.altAxis:st,ct=f&&ot?function(t,e,i){var n=ae(t,e,i);return n>i?i:n}(at,et,lt):ae(f?at:nt,et,f?lt:st);A[w]=ct,k[w]=ct-et}e.modifiersData[n]=k}},requiresIfExists:["offset"]};function $e(t,e,i){void 0===i&&(i=!1);var n,s,o=zt(e),r=zt(e)&&function(t){var e=t.getBoundingClientRect(),i=Xt(e.width)/t.offsetWidth||1,n=Xt(e.height)/t.offsetHeight||1;return 1!==i||1!==n}(e),a=ie(e),l=Gt(t,r,i),c={scrollLeft:0,scrollTop:0},h={x:0,y:0};return(o||!o&&!i)&&(("body"!==Wt(e)||Ee(a))&&(c=(n=e)!==Bt(n)&&zt(n)?{scrollLeft:(s=n).scrollLeft,scrollTop:s.scrollTop}:we(n)),zt(e)?((h=Gt(e,!0)).x+=e.clientLeft,h.y+=e.clientTop):a&&(h.x=Ae(a))),{x:l.left+c.scrollLeft-h.x,y:l.top+c.scrollTop-h.y,width:l.width,height:l.height}}function We(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}var Be={placement:"bottom",modifiers:[],strategy:"absolute"};function Fe(){for(var t=arguments.length,e=new Array(t),i=0;iNumber.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||"static"===this._config.display)&&(B.setDataAttribute(this._menu,"popper","static"),t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,..."function"==typeof this._config.popperConfig?this._config.popperConfig(t):this._config.popperConfig}}_selectMenuItem({key:t,target:e}){const i=Q.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter((t=>a(t)));i.length&&b(i,e,t===Ye,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=hi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(2===t.button||"keyup"===t.type&&"Tab"!==t.key)return;const e=Q.find(ti);for(const i of e){const e=hi.getInstance(i);if(!e||!1===e._config.autoClose)continue;const n=t.composedPath(),s=n.includes(e._menu);if(n.includes(e._element)||"inside"===e._config.autoClose&&!s||"outside"===e._config.autoClose&&s)continue;if(e._menu.contains(t.target)&&("keyup"===t.type&&"Tab"===t.key||/input|select|option|textarea|form/i.test(t.target.tagName)))continue;const o={relatedTarget:e._element};"click"===t.type&&(o.clickEvent=t),e._completeHide(o)}}static dataApiKeydownHandler(t){const e=/input|textarea/i.test(t.target.tagName),i="Escape"===t.key,n=[Xe,Ye].includes(t.key);if(!n&&!i)return;if(e&&!i)return;t.preventDefault();const s=this.matches(Ze)?this:Q.prev(this,Ze)[0]||Q.next(this,Ze)[0]||Q.findOne(Ze,t.delegateTarget.parentNode),o=hi.getOrCreateInstance(s);if(n)return t.stopPropagation(),o.show(),void o._selectMenuItem(t);o._isShown()&&(t.stopPropagation(),o.hide(),s.focus())}}P.on(document,Ge,Ze,hi.dataApiKeydownHandler),P.on(document,Ge,ei,hi.dataApiKeydownHandler),P.on(document,Ue,hi.clearMenus),P.on(document,"keyup.bs.dropdown.data-api",hi.clearMenus),P.on(document,Ue,Ze,(function(t){t.preventDefault(),hi.getOrCreateInstance(this).toggle()})),g(hi);const di=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",ui=".sticky-top",fi="padding-right",pi="margin-right";class gi{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,fi,(e=>e+t)),this._setElementAttributes(di,fi,(e=>e+t)),this._setElementAttributes(ui,pi,(e=>e-t))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,fi),this._resetElementAttributes(di,fi),this._resetElementAttributes(ui,pi)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t).getPropertyValue(e);t.style.setProperty(e,`${i(Number.parseFloat(s))}px`)}))}_saveInitialAttribute(t,e){const i=t.style.getPropertyValue(e);i&&B.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=B.getDataAttribute(t,e);null!==i?(B.removeDataAttribute(t,e),t.style.setProperty(e,i)):t.style.removeProperty(e)}))}_applyManipulationCallback(t,e){if(o(t))e(t);else for(const i of Q.find(t,this._element))e(i)}}const mi="show",_i="mousedown.bs.backdrop",bi={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},vi={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class yi extends F{constructor(t){super(),this._config=this._getConfig(t),this._isAppended=!1,this._element=null}static get Default(){return bi}static get DefaultType(){return vi}static get NAME(){return"backdrop"}show(t){if(!this._config.isVisible)return void m(t);this._append();const e=this._getElement();this._config.isAnimated&&d(e),e.classList.add(mi),this._emulateAnimation((()=>{m(t)}))}hide(t){this._config.isVisible?(this._getElement().classList.remove(mi),this._emulateAnimation((()=>{this.dispose(),m(t)}))):m(t)}dispose(){this._isAppended&&(P.off(this._element,_i),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_configAfterMerge(t){return t.rootElement=r(t.rootElement),t}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),P.on(t,_i,(()=>{m(this._config.clickCallback)})),this._isAppended=!0}_emulateAnimation(t){_(t,this._getElement(),this._config.isAnimated)}}const wi=".bs.focustrap",Ai="backward",Ei={autofocus:!0,trapElement:null},Ti={autofocus:"boolean",trapElement:"element"};class Ci extends F{constructor(t){super(),this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return Ei}static get DefaultType(){return Ti}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),P.off(document,wi),P.on(document,"focusin.bs.focustrap",(t=>this._handleFocusin(t))),P.on(document,"keydown.tab.bs.focustrap",(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,P.off(document,wi))}_handleFocusin(t){const{trapElement:e}=this._config;if(t.target===document||t.target===e||e.contains(t.target))return;const i=Q.focusableChildren(e);0===i.length?e.focus():this._lastTabNavDirection===Ai?i[i.length-1].focus():i[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?Ai:"forward")}}const Oi="hidden.bs.modal",xi="show.bs.modal",ki="modal-open",Li="show",Di="modal-static",Si={backdrop:!0,focus:!0,keyboard:!0},Ii={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class Ni extends z{constructor(t,e){super(t,e),this._dialog=Q.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new gi,this._addEventListeners()}static get Default(){return Si}static get DefaultType(){return Ii}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||P.trigger(this._element,xi,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(ki),this._adjustDialog(),this._backdrop.show((()=>this._showElement(t))))}hide(){this._isShown&&!this._isTransitioning&&(P.trigger(this._element,"hide.bs.modal").defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(Li),this._queueCallback((()=>this._hideModal()),this._element,this._isAnimated())))}dispose(){for(const t of[window,this._dialog])P.off(t,".bs.modal");this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new yi({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new Ci({trapElement:this._element})}_showElement(t){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const e=Q.findOne(".modal-body",this._dialog);e&&(e.scrollTop=0),d(this._element),this._element.classList.add(Li),this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,P.trigger(this._element,"shown.bs.modal",{relatedTarget:t})}),this._dialog,this._isAnimated())}_addEventListeners(){P.on(this._element,"keydown.dismiss.bs.modal",(t=>{if("Escape"===t.key)return this._config.keyboard?(t.preventDefault(),void this.hide()):void this._triggerBackdropTransition()})),P.on(window,"resize.bs.modal",(()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()})),P.on(this._element,"mousedown.dismiss.bs.modal",(t=>{P.one(this._element,"click.dismiss.bs.modal",(e=>{this._element===t.target&&this._element===e.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())}))}))}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(ki),this._resetAdjustments(),this._scrollBar.reset(),P.trigger(this._element,Oi)}))}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(P.trigger(this._element,"hidePrevented.bs.modal").defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._element.style.overflowY;"hidden"===e||this._element.classList.contains(Di)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(Di),this._queueCallback((()=>{this._element.classList.remove(Di),this._queueCallback((()=>{this._element.style.overflowY=e}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;if(i&&!t){const t=p()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!i&&t){const t=p()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=Ni.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}P.on(document,"click.bs.modal.data-api",'[data-bs-toggle="modal"]',(function(t){const e=n(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),P.one(e,xi,(t=>{t.defaultPrevented||P.one(e,Oi,(()=>{a(this)&&this.focus()}))}));const i=Q.findOne(".modal.show");i&&Ni.getInstance(i).hide(),Ni.getOrCreateInstance(e).toggle(this)})),q(Ni),g(Ni);const Pi="show",ji="showing",Mi="hiding",Hi=".offcanvas.show",$i="hidePrevented.bs.offcanvas",Wi="hidden.bs.offcanvas",Bi={backdrop:!0,keyboard:!0,scroll:!1},Fi={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class zi extends z{constructor(t,e){super(t,e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return Bi}static get DefaultType(){return Fi}static get NAME(){return"offcanvas"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||P.trigger(this._element,"show.bs.offcanvas",{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._backdrop.show(),this._config.scroll||(new gi).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(ji),this._queueCallback((()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(Pi),this._element.classList.remove(ji),P.trigger(this._element,"shown.bs.offcanvas",{relatedTarget:t})}),this._element,!0))}hide(){this._isShown&&(P.trigger(this._element,"hide.bs.offcanvas").defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add(Mi),this._backdrop.hide(),this._queueCallback((()=>{this._element.classList.remove(Pi,Mi),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new gi).reset(),P.trigger(this._element,Wi)}),this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const t=Boolean(this._config.backdrop);return new yi({className:"offcanvas-backdrop",isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?()=>{"static"!==this._config.backdrop?this.hide():P.trigger(this._element,$i)}:null})}_initializeFocusTrap(){return new Ci({trapElement:this._element})}_addEventListeners(){P.on(this._element,"keydown.dismiss.bs.offcanvas",(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():P.trigger(this._element,$i))}))}static jQueryInterface(t){return this.each((function(){const e=zi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}P.on(document,"click.bs.offcanvas.data-api",'[data-bs-toggle="offcanvas"]',(function(t){const e=n(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this))return;P.one(e,Wi,(()=>{a(this)&&this.focus()}));const i=Q.findOne(Hi);i&&i!==e&&zi.getInstance(i).hide(),zi.getOrCreateInstance(e).toggle(this)})),P.on(window,"load.bs.offcanvas.data-api",(()=>{for(const t of Q.find(Hi))zi.getOrCreateInstance(t).show()})),P.on(window,"resize.bs.offcanvas",(()=>{for(const t of Q.find("[aria-modal][class*=show][class*=offcanvas-]"))"fixed"!==getComputedStyle(t).position&&zi.getOrCreateInstance(t).hide()})),q(zi),g(zi);const qi=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Ri=/^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i,Vi=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i,Ki=(t,e)=>{const i=t.nodeName.toLowerCase();return e.includes(i)?!qi.has(i)||Boolean(Ri.test(t.nodeValue)||Vi.test(t.nodeValue)):e.filter((t=>t instanceof RegExp)).some((t=>t.test(i)))},Qi={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Xi={allowList:Qi,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
"},Yi={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},Ui={entry:"(string|element|function|null)",selector:"(string|element)"};class Gi extends F{constructor(t){super(),this._config=this._getConfig(t)}static get Default(){return Xi}static get DefaultType(){return Yi}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map((t=>this._resolvePossibleFunction(t))).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(t){return this._checkContent(t),this._config.content={...this._config.content,...t},this}toHtml(){const t=document.createElement("div");t.innerHTML=this._maybeSanitize(this._config.template);for(const[e,i]of Object.entries(this._config.content))this._setContent(t,i,e);const e=t.children[0],i=this._resolvePossibleFunction(this._config.extraClass);return i&&e.classList.add(...i.split(" ")),e}_typeCheckConfig(t){super._typeCheckConfig(t),this._checkContent(t.content)}_checkContent(t){for(const[e,i]of Object.entries(t))super._typeCheckConfig({selector:e,entry:i},Ui)}_setContent(t,e,i){const n=Q.findOne(i,t);n&&((e=this._resolvePossibleFunction(e))?o(e)?this._putElementInTemplate(r(e),n):this._config.html?n.innerHTML=this._maybeSanitize(e):n.textContent=e:n.remove())}_maybeSanitize(t){return this._config.sanitize?function(t,e,i){if(!t.length)return t;if(i&&"function"==typeof i)return i(t);const n=(new window.DOMParser).parseFromString(t,"text/html"),s=[].concat(...n.body.querySelectorAll("*"));for(const t of s){const i=t.nodeName.toLowerCase();if(!Object.keys(e).includes(i)){t.remove();continue}const n=[].concat(...t.attributes),s=[].concat(e["*"]||[],e[i]||[]);for(const e of n)Ki(e,s)||t.removeAttribute(e.nodeName)}return n.body.innerHTML}(t,this._config.allowList,this._config.sanitizeFn):t}_resolvePossibleFunction(t){return"function"==typeof t?t(this):t}_putElementInTemplate(t,e){if(this._config.html)return e.innerHTML="",void e.append(t);e.textContent=t.textContent}}const Ji=new Set(["sanitize","allowList","sanitizeFn"]),Zi="fade",tn="show",en=".modal",nn="hide.bs.modal",sn="hover",on="focus",rn={AUTO:"auto",TOP:"top",RIGHT:p()?"left":"right",BOTTOM:"bottom",LEFT:p()?"right":"left"},an={allowList:Qi,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,0],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},ln={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class cn extends z{constructor(t,e){if(void 0===Ke)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t,e),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return an}static get DefaultType(){return ln}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._activeTrigger.click=!this._activeTrigger.click,this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),P.off(this._element.closest(en),nn,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const t=P.trigger(this._element,this.constructor.eventName("show")),e=(c(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(t.defaultPrevented||!e)return;this._disposePopper();const i=this._getTipElement();this._element.setAttribute("aria-describedby",i.getAttribute("id"));const{container:n}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(n.append(i),P.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(i),i.classList.add(tn),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))P.on(t,"mouseover",h);this._queueCallback((()=>{P.trigger(this._element,this.constructor.eventName("shown")),!1===this._isHovered&&this._leave(),this._isHovered=!1}),this.tip,this._isAnimated())}hide(){if(this._isShown()&&!P.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented){if(this._getTipElement().classList.remove(tn),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))P.off(t,"mouseover",h);this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,this._isHovered=null,this._queueCallback((()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),P.trigger(this._element,this.constructor.eventName("hidden")))}),this.tip,this._isAnimated())}}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(t){const e=this._getTemplateFactory(t).toHtml();if(!e)return null;e.classList.remove(Zi,tn),e.classList.add(`bs-${this.constructor.NAME}-auto`);const i=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME).toString();return e.setAttribute("id",i),this._isAnimated()&&e.classList.add(Zi),e}setContent(t){this._newContent=t,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(t){return this._templateFactory?this._templateFactory.changeContent(t):this._templateFactory=new Gi({...this._config,content:t,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{".tooltip-inner":this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(t){return this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(Zi)}_isShown(){return this.tip&&this.tip.classList.contains(tn)}_createPopper(t){const e="function"==typeof this._config.placement?this._config.placement.call(this,t,this._element):this._config.placement,i=rn[e.toUpperCase()];return Ve(this._element,t,this._getPopperConfig(i))}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return"function"==typeof t?t.call(this._element):t}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:t=>{this._getTipElement().setAttribute("data-popper-placement",t.state.placement)}}]};return{...e,..."function"==typeof this._config.popperConfig?this._config.popperConfig(e):this._config.popperConfig}}_setListeners(){const t=this._config.trigger.split(" ");for(const e of t)if("click"===e)P.on(this._element,this.constructor.eventName("click"),this._config.selector,(t=>{this._initializeOnDelegatedTarget(t).toggle()}));else if("manual"!==e){const t=e===sn?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),i=e===sn?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");P.on(this._element,t,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusin"===t.type?on:sn]=!0,e._enter()})),P.on(this._element,i,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusout"===t.type?on:sn]=e._element.contains(t.relatedTarget),e._leave()}))}this._hideModalHandler=()=>{this._element&&this.hide()},P.on(this._element.closest(en),nn,this._hideModalHandler)}_fixTitle(){const t=this._element.getAttribute("title");t&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",t),this._element.setAttribute("data-bs-original-title",t),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout((()=>{this._isHovered&&this.show()}),this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout((()=>{this._isHovered||this.hide()}),this._config.delay.hide))}_setTimeout(t,e){clearTimeout(this._timeout),this._timeout=setTimeout(t,e)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(t){const e=B.getDataAttributes(this._element);for(const t of Object.keys(e))Ji.has(t)&&delete e[t];return t={...e,..."object"==typeof t&&t?t:{}},t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t.container=!1===t.container?document.body:r(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),t}_getDelegateConfig(){const t={};for(const e in this._config)this.constructor.Default[e]!==this._config[e]&&(t[e]=this._config[e]);return t.selector=!1,t.trigger="manual",t}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(t){return this.each((function(){const e=cn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}g(cn);const hn={...cn.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},dn={...cn.DefaultType,content:"(null|string|element|function)"};class un extends cn{static get Default(){return hn}static get DefaultType(){return dn}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{".popover-header":this._getTitle(),".popover-body":this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(t){return this.each((function(){const e=un.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}g(un);const fn="click.bs.scrollspy",pn="active",gn="[href]",mn={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},_n={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class bn extends z{constructor(t,e){super(t,e),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement="visible"===getComputedStyle(this._element).overflowY?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return mn}static get DefaultType(){return _n}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const t of this._observableSections.values())this._observer.observe(t)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(t){return t.target=r(t.target)||document.body,t.rootMargin=t.offset?`${t.offset}px 0px -30%`:t.rootMargin,"string"==typeof t.threshold&&(t.threshold=t.threshold.split(",").map((t=>Number.parseFloat(t)))),t}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(P.off(this._config.target,fn),P.on(this._config.target,fn,gn,(t=>{const e=this._observableSections.get(t.target.hash);if(e){t.preventDefault();const i=this._rootElement||window,n=e.offsetTop-this._element.offsetTop;if(i.scrollTo)return void i.scrollTo({top:n,behavior:"smooth"});i.scrollTop=n}})))}_getNewObserver(){const t={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver((t=>this._observerCallback(t)),t)}_observerCallback(t){const e=t=>this._targetLinks.get(`#${t.target.id}`),i=t=>{this._previousScrollData.visibleEntryTop=t.target.offsetTop,this._process(e(t))},n=(this._rootElement||document.documentElement).scrollTop,s=n>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=n;for(const o of t){if(!o.isIntersecting){this._activeTarget=null,this._clearActiveClass(e(o));continue}const t=o.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(s&&t){if(i(o),!n)return}else s||t||i(o)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const t=Q.find(gn,this._config.target);for(const e of t){if(!e.hash||l(e))continue;const t=Q.findOne(e.hash,this._element);a(t)&&(this._targetLinks.set(e.hash,e),this._observableSections.set(e.hash,t))}}_process(t){this._activeTarget!==t&&(this._clearActiveClass(this._config.target),this._activeTarget=t,t.classList.add(pn),this._activateParents(t),P.trigger(this._element,"activate.bs.scrollspy",{relatedTarget:t}))}_activateParents(t){if(t.classList.contains("dropdown-item"))Q.findOne(".dropdown-toggle",t.closest(".dropdown")).classList.add(pn);else for(const e of Q.parents(t,".nav, .list-group"))for(const t of Q.prev(e,".nav-link, .nav-item > .nav-link, .list-group-item"))t.classList.add(pn)}_clearActiveClass(t){t.classList.remove(pn);const e=Q.find("[href].active",t);for(const t of e)t.classList.remove(pn)}static jQueryInterface(t){return this.each((function(){const e=bn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}P.on(window,"load.bs.scrollspy.data-api",(()=>{for(const t of Q.find('[data-bs-spy="scroll"]'))bn.getOrCreateInstance(t)})),g(bn);const vn="ArrowLeft",yn="ArrowRight",wn="ArrowUp",An="ArrowDown",En="active",Tn="fade",Cn="show",On='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',xn=`.nav-link:not(.dropdown-toggle), .list-group-item:not(.dropdown-toggle), [role="tab"]:not(.dropdown-toggle), ${On}`;class kn extends z{constructor(t){super(t),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),P.on(this._element,"keydown.bs.tab",(t=>this._keydown(t))))}static get NAME(){return"tab"}show(){const t=this._element;if(this._elemIsActive(t))return;const e=this._getActiveElem(),i=e?P.trigger(e,"hide.bs.tab",{relatedTarget:t}):null;P.trigger(t,"show.bs.tab",{relatedTarget:e}).defaultPrevented||i&&i.defaultPrevented||(this._deactivate(e,t),this._activate(t,e))}_activate(t,e){t&&(t.classList.add(En),this._activate(n(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.removeAttribute("tabindex"),t.setAttribute("aria-selected",!0),this._toggleDropDown(t,!0),P.trigger(t,"shown.bs.tab",{relatedTarget:e})):t.classList.add(Cn)}),t,t.classList.contains(Tn)))}_deactivate(t,e){t&&(t.classList.remove(En),t.blur(),this._deactivate(n(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.setAttribute("aria-selected",!1),t.setAttribute("tabindex","-1"),this._toggleDropDown(t,!1),P.trigger(t,"hidden.bs.tab",{relatedTarget:e})):t.classList.remove(Cn)}),t,t.classList.contains(Tn)))}_keydown(t){if(![vn,yn,wn,An].includes(t.key))return;t.stopPropagation(),t.preventDefault();const e=[yn,An].includes(t.key),i=b(this._getChildren().filter((t=>!l(t))),t.target,e,!0);i&&(i.focus({preventScroll:!0}),kn.getOrCreateInstance(i).show())}_getChildren(){return Q.find(xn,this._parent)}_getActiveElem(){return this._getChildren().find((t=>this._elemIsActive(t)))||null}_setInitialAttributes(t,e){this._setAttributeIfNotExists(t,"role","tablist");for(const t of e)this._setInitialAttributesOnChild(t)}_setInitialAttributesOnChild(t){t=this._getInnerElement(t);const e=this._elemIsActive(t),i=this._getOuterElement(t);t.setAttribute("aria-selected",e),i!==t&&this._setAttributeIfNotExists(i,"role","presentation"),e||t.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(t,"role","tab"),this._setInitialAttributesOnTargetPanel(t)}_setInitialAttributesOnTargetPanel(t){const e=n(t);e&&(this._setAttributeIfNotExists(e,"role","tabpanel"),t.id&&this._setAttributeIfNotExists(e,"aria-labelledby",`#${t.id}`))}_toggleDropDown(t,e){const i=this._getOuterElement(t);if(!i.classList.contains("dropdown"))return;const n=(t,n)=>{const s=Q.findOne(t,i);s&&s.classList.toggle(n,e)};n(".dropdown-toggle",En),n(".dropdown-menu",Cn),i.setAttribute("aria-expanded",e)}_setAttributeIfNotExists(t,e,i){t.hasAttribute(e)||t.setAttribute(e,i)}_elemIsActive(t){return t.classList.contains(En)}_getInnerElement(t){return t.matches(xn)?t:Q.findOne(xn,t)}_getOuterElement(t){return t.closest(".nav-item, .list-group-item")||t}static jQueryInterface(t){return this.each((function(){const e=kn.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}P.on(document,"click.bs.tab",On,(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this)||kn.getOrCreateInstance(this).show()})),P.on(window,"load.bs.tab",(()=>{for(const t of Q.find('.active[data-bs-toggle="tab"], .active[data-bs-toggle="pill"], .active[data-bs-toggle="list"]'))kn.getOrCreateInstance(t)})),g(kn);const Ln="hide",Dn="show",Sn="showing",In={animation:"boolean",autohide:"boolean",delay:"number"},Nn={animation:!0,autohide:!0,delay:5e3};class Pn extends z{constructor(t,e){super(t,e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return Nn}static get DefaultType(){return In}static get NAME(){return"toast"}show(){P.trigger(this._element,"show.bs.toast").defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(Ln),d(this._element),this._element.classList.add(Dn,Sn),this._queueCallback((()=>{this._element.classList.remove(Sn),P.trigger(this._element,"shown.bs.toast"),this._maybeScheduleHide()}),this._element,this._config.animation))}hide(){this.isShown()&&(P.trigger(this._element,"hide.bs.toast").defaultPrevented||(this._element.classList.add(Sn),this._queueCallback((()=>{this._element.classList.add(Ln),this._element.classList.remove(Sn,Dn),P.trigger(this._element,"hidden.bs.toast")}),this._element,this._config.animation)))}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(Dn),super.dispose()}isShown(){return this._element.classList.contains(Dn)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){P.on(this._element,"mouseover.bs.toast",(t=>this._onInteraction(t,!0))),P.on(this._element,"mouseout.bs.toast",(t=>this._onInteraction(t,!1))),P.on(this._element,"focusin.bs.toast",(t=>this._onInteraction(t,!0))),P.on(this._element,"focusout.bs.toast",(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=Pn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return q(Pn),g(Pn),{Alert:R,Button:K,Carousel:at,Collapse:pt,Dropdown:hi,Modal:Ni,Offcanvas:zi,Popover:un,ScrollSpy:bn,Tab:kn,Toast:Pn,Tooltip:cn}})); +//# sourceMappingURL=bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/django/static/bootstrap.min.css b/django/static/bootstrap.min.css new file mode 100644 index 0000000..f06f523 --- /dev/null +++ b/django/static/bootstrap.min.css @@ -0,0 +1,7 @@ +@charset "UTF-8";/*! + * Bootstrap v5.2.3 (https://getbootstrap.com/) + * Copyright 2011-2022 The Bootstrap Authors + * Copyright 2011-2022 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-body-color-rgb:33,37,41;--bs-body-bg-rgb:255,255,255;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-bg:#fff;--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0, 0, 0, 0.175);--bs-border-radius:0.375rem;--bs-border-radius-sm:0.25rem;--bs-border-radius-lg:0.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-2xl:2rem;--bs-border-radius-pill:50rem;--bs-link-color:#0d6efd;--bs-link-hover-color:#0a58ca;--bs-code-color:#d63384;--bs-highlight-bg:#fff3cd}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;border:0;border-top:1px solid;opacity:.25}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.1875em;background-color:var(--bs-highlight-bg)}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:var(--bs-link-color);text-decoration:underline}a:hover{color:var(--bs-link-hover-color)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:var(--bs-code-color);word-wrap:break-word}a>code{color:inherit}kbd{padding:.1875rem .375rem;font-size:.875em;color:var(--bs-body-bg);background-color:var(--bs-body-color);border-radius:.25rem}kbd kbd{padding:0;font-size:1em}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none!important}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}::file-selector-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media (min-width:1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid var(--bs-border-color);border-radius:.375rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:#6c757d}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{--bs-gutter-x:1.5rem;--bs-gutter-y:0;width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}@media (min-width:1400px){.container,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{max-width:1320px}}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(-1 * var(--bs-gutter-y));margin-right:calc(-.5 * var(--bs-gutter-x));margin-left:calc(-.5 * var(--bs-gutter-x))}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-top:var(--bs-gutter-y)}.col{flex:1 0 0%}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.6666666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.33333333%}.col-2{flex:0 0 auto;width:16.66666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.33333333%}.col-5{flex:0 0 auto;width:41.66666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.33333333%}.col-8{flex:0 0 auto;width:66.66666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.33333333%}.col-11{flex:0 0 auto;width:91.66666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}.g-0,.gx-0{--bs-gutter-x:0}.g-0,.gy-0{--bs-gutter-y:0}.g-1,.gx-1{--bs-gutter-x:0.25rem}.g-1,.gy-1{--bs-gutter-y:0.25rem}.g-2,.gx-2{--bs-gutter-x:0.5rem}.g-2,.gy-2{--bs-gutter-y:0.5rem}.g-3,.gx-3{--bs-gutter-x:1rem}.g-3,.gy-3{--bs-gutter-y:1rem}.g-4,.gx-4{--bs-gutter-x:1.5rem}.g-4,.gy-4{--bs-gutter-y:1.5rem}.g-5,.gx-5{--bs-gutter-x:3rem}.g-5,.gy-5{--bs-gutter-y:3rem}@media (min-width:576px){.col-sm{flex:1 0 0%}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.6666666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.33333333%}.col-sm-2{flex:0 0 auto;width:16.66666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.33333333%}.col-sm-5{flex:0 0 auto;width:41.66666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.33333333%}.col-sm-8{flex:0 0 auto;width:66.66666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.33333333%}.col-sm-11{flex:0 0 auto;width:91.66666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x:0}.g-sm-0,.gy-sm-0{--bs-gutter-y:0}.g-sm-1,.gx-sm-1{--bs-gutter-x:0.25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y:0.25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x:0.5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y:0.5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x:1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y:1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x:1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y:1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x:3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y:3rem}}@media (min-width:768px){.col-md{flex:1 0 0%}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.6666666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.33333333%}.col-md-2{flex:0 0 auto;width:16.66666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-5{flex:0 0 auto;width:41.66666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-11{flex:0 0 auto;width:91.66666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}.g-md-0,.gx-md-0{--bs-gutter-x:0}.g-md-0,.gy-md-0{--bs-gutter-y:0}.g-md-1,.gx-md-1{--bs-gutter-x:0.25rem}.g-md-1,.gy-md-1{--bs-gutter-y:0.25rem}.g-md-2,.gx-md-2{--bs-gutter-x:0.5rem}.g-md-2,.gy-md-2{--bs-gutter-y:0.5rem}.g-md-3,.gx-md-3{--bs-gutter-x:1rem}.g-md-3,.gy-md-3{--bs-gutter-y:1rem}.g-md-4,.gx-md-4{--bs-gutter-x:1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y:1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x:3rem}.g-md-5,.gy-md-5{--bs-gutter-y:3rem}}@media (min-width:992px){.col-lg{flex:1 0 0%}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.6666666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.33333333%}.col-lg-2{flex:0 0 auto;width:16.66666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.33333333%}.col-lg-11{flex:0 0 auto;width:91.66666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x:0}.g-lg-0,.gy-lg-0{--bs-gutter-y:0}.g-lg-1,.gx-lg-1{--bs-gutter-x:0.25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y:0.25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x:0.5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y:0.5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x:1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y:1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x:1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y:1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x:3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y:3rem}}@media (min-width:1200px){.col-xl{flex:1 0 0%}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.33333333%}.col-xl-2{flex:0 0 auto;width:16.66666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.33333333%}.col-xl-5{flex:0 0 auto;width:41.66666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.33333333%}.col-xl-8{flex:0 0 auto;width:66.66666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.33333333%}.col-xl-11{flex:0 0 auto;width:91.66666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x:0}.g-xl-0,.gy-xl-0{--bs-gutter-y:0}.g-xl-1,.gx-xl-1{--bs-gutter-x:0.25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y:0.25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x:0.5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y:0.5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x:1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y:1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x:1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y:1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x:3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y:3rem}}@media (min-width:1400px){.col-xxl{flex:1 0 0%}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.33333333%}.col-xxl-2{flex:0 0 auto;width:16.66666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.33333333%}.col-xxl-5{flex:0 0 auto;width:41.66666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.33333333%}.col-xxl-8{flex:0 0 auto;width:66.66666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.33333333%}.col-xxl-11{flex:0 0 auto;width:91.66666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x:0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y:0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x:0.25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y:0.25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x:0.5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y:0.5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x:1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y:1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x:1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y:1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x:3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y:3rem}}.table{--bs-table-color:var(--bs-body-color);--bs-table-bg:transparent;--bs-table-border-color:var(--bs-border-color);--bs-table-accent-bg:transparent;--bs-table-striped-color:var(--bs-body-color);--bs-table-striped-bg:rgba(0, 0, 0, 0.05);--bs-table-active-color:var(--bs-body-color);--bs-table-active-bg:rgba(0, 0, 0, 0.1);--bs-table-hover-color:var(--bs-body-color);--bs-table-hover-bg:rgba(0, 0, 0, 0.075);width:100%;margin-bottom:1rem;color:var(--bs-table-color);vertical-align:top;border-color:var(--bs-table-border-color)}.table>:not(caption)>*>*{padding:.5rem .5rem;background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-accent-bg)}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table-group-divider{border-top:2px solid currentcolor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-accent-bg:var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-striped-columns>:not(caption)>tr>:nth-child(2n){--bs-table-accent-bg:var(--bs-table-striped-bg);color:var(--bs-table-striped-color)}.table-active{--bs-table-accent-bg:var(--bs-table-active-bg);color:var(--bs-table-active-color)}.table-hover>tbody>tr:hover>*{--bs-table-accent-bg:var(--bs-table-hover-bg);color:var(--bs-table-hover-color)}.table-primary{--bs-table-color:#000;--bs-table-bg:#cfe2ff;--bs-table-border-color:#bacbe6;--bs-table-striped-bg:#c5d7f2;--bs-table-striped-color:#000;--bs-table-active-bg:#bacbe6;--bs-table-active-color:#000;--bs-table-hover-bg:#bfd1ec;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-secondary{--bs-table-color:#000;--bs-table-bg:#e2e3e5;--bs-table-border-color:#cbccce;--bs-table-striped-bg:#d7d8da;--bs-table-striped-color:#000;--bs-table-active-bg:#cbccce;--bs-table-active-color:#000;--bs-table-hover-bg:#d1d2d4;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-success{--bs-table-color:#000;--bs-table-bg:#d1e7dd;--bs-table-border-color:#bcd0c7;--bs-table-striped-bg:#c7dbd2;--bs-table-striped-color:#000;--bs-table-active-bg:#bcd0c7;--bs-table-active-color:#000;--bs-table-hover-bg:#c1d6cc;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-info{--bs-table-color:#000;--bs-table-bg:#cff4fc;--bs-table-border-color:#badce3;--bs-table-striped-bg:#c5e8ef;--bs-table-striped-color:#000;--bs-table-active-bg:#badce3;--bs-table-active-color:#000;--bs-table-hover-bg:#bfe2e9;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-warning{--bs-table-color:#000;--bs-table-bg:#fff3cd;--bs-table-border-color:#e6dbb9;--bs-table-striped-bg:#f2e7c3;--bs-table-striped-color:#000;--bs-table-active-bg:#e6dbb9;--bs-table-active-color:#000;--bs-table-hover-bg:#ece1be;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-danger{--bs-table-color:#000;--bs-table-bg:#f8d7da;--bs-table-border-color:#dfc2c4;--bs-table-striped-bg:#eccccf;--bs-table-striped-color:#000;--bs-table-active-bg:#dfc2c4;--bs-table-active-color:#000;--bs-table-hover-bg:#e5c7ca;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-light{--bs-table-color:#000;--bs-table-bg:#f8f9fa;--bs-table-border-color:#dfe0e1;--bs-table-striped-bg:#ecedee;--bs-table-striped-color:#000;--bs-table-active-bg:#dfe0e1;--bs-table-active-color:#000;--bs-table-hover-bg:#e5e6e7;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-dark{--bs-table-color:#fff;--bs-table-bg:#212529;--bs-table-border-color:#373b3e;--bs-table-striped-bg:#2c3034;--bs-table-striped-color:#fff;--bs-table-active-bg:#373b3e;--bs-table-active-color:#fff;--bs-table-hover-bg:#323539;--bs-table-hover-color:#fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media (max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:#6c757d}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:#212529;background-color:#fff;border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-control::-webkit-date-and-time-value{height:1.5em}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled{background-color:#e9ecef;opacity:1}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:#212529;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:#212529;background-color:#e9ecef;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::-webkit-file-upload-button{-webkit-transition:none;transition:none}.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:#dde0e3}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#dde0e3}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext:focus{outline:0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;border-radius:.25rem}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;border-radius:.5rem}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + .75rem + 2px)}textarea.form-control-sm{min-height:calc(1.5em + .5rem + 2px)}textarea.form-control-lg{min-height:calc(1.5em + 1rem + 2px)}.form-control-color{width:3rem;height:calc(1.5em + .75rem + 2px);padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0!important;border-radius:.375rem}.form-control-color::-webkit-color-swatch{border-radius:.375rem}.form-control-color.form-control-sm{height:calc(1.5em + .5rem + 2px)}.form-control-color.form-control-lg{height:calc(1.5em + 1rem + 2px)}.form-select{display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;-moz-padding-start:calc(0.75rem - 3px);font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid #ced4da;border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:#e9ecef}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #212529}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem;border-radius:.25rem}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem;border-radius:.5rem}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-reverse{padding-right:1.5em;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:-1.5em;margin-left:0}.form-check-input{width:1em;height:1em;margin-top:.25em;vertical-align:top;background-color:#fff;background-repeat:no-repeat;background-position:center;background-size:contain;border:1px solid rgba(0,0,0,.25);-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-print-color-adjust:exact;color-adjust:exact;print-color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#0d6efd;border-color:#0d6efd;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{cursor:default;opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{width:2em;margin-left:-2.5em;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-switch.form-check-reverse{padding-right:2.5em;padding-left:0}.form-switch.form-check-reverse .form-check-input{margin-right:-2.5em;margin-left:0}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check:disabled+.btn,.btn-check[disabled]+.btn{pointer-events:none;filter:none;opacity:.65}.form-range{width:100%;height:1.5rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#0d6efd;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b6d4fe}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#0d6efd;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{-moz-transition:none;transition:none}}.form-range::-moz-range-thumb:active{background-color:#b6d4fe}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.form-range:disabled::-moz-range-thumb{background-color:#adb5bd}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + 2px);line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;width:100%;height:100%;padding:1rem .75rem;overflow:hidden;text-align:start;text-overflow:ellipsis;white-space:nowrap;pointer-events:none;border:1px solid transparent;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem .75rem}.form-floating>.form-control-plaintext::-moz-placeholder,.form-floating>.form-control::-moz-placeholder{color:transparent}.form-floating>.form-control-plaintext::placeholder,.form-floating>.form-control::placeholder{color:transparent}.form-floating>.form-control-plaintext:not(:-moz-placeholder-shown),.form-floating>.form-control:not(:-moz-placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown),.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control-plaintext:-webkit-autofill,.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:not(:-moz-placeholder-shown)~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control-plaintext~label,.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:-webkit-autofill~label{opacity:.65;transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control-plaintext~label{border-width:1px 0}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-floating,.input-group>.form-select{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-floating:focus-within,.input-group>.form-select:focus{z-index:5}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:5}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.375rem}.input-group-lg>.btn,.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;border-radius:.5rem}.input-group-sm>.btn,.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text{padding:.25rem .5rem;font-size:.875rem;border-radius:.25rem}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select,.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select,.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:-1px;border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select{border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#198754}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(25,135,84,.9);border-radius:.375rem}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#198754;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-valid,.was-validated .form-select:valid{border-color:#198754}.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"],.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-valid:focus,.was-validated .form-select:valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.form-control-color.is-valid,.was-validated .form-control-color:valid{width:calc(3rem + calc(1.5em + .75rem))}.form-check-input.is-valid,.was-validated .form-check-input:valid{border-color:#198754}.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked{background-color:#198754}.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#198754}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-valid,.input-group>.form-floating:not(:focus-within).is-valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-control:not(:focus):valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.was-validated .input-group>.form-select:not(:focus):valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.375rem}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-invalid,.was-validated .form-select:invalid{border-color:#dc3545}.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"]{padding-right:4.125rem;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"),url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-invalid:focus,.was-validated .form-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.form-control-color.is-invalid,.was-validated .form-control-color:invalid{width:calc(3rem + calc(1.5em + .75rem))}.form-check-input.is-invalid,.was-validated .form-check-input:invalid{border-color:#dc3545}.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked{background-color:#dc3545}.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-invalid,.input-group>.form-floating:not(:focus-within).is-invalid,.input-group>.form-select:not(:focus).is-invalid,.was-validated .input-group>.form-control:not(:focus):invalid,.was-validated .input-group>.form-floating:not(:focus-within):invalid,.was-validated .input-group>.form-select:not(:focus):invalid{z-index:4}.btn{--bs-btn-padding-x:0.75rem;--bs-btn-padding-y:0.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight:400;--bs-btn-line-height:1.5;--bs-btn-color:#212529;--bs-btn-bg:transparent;--bs-btn-border-width:1px;--bs-btn-border-color:transparent;--bs-btn-border-radius:0.375rem;--bs-btn-hover-border-color:transparent;--bs-btn-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.15),0 1px 1px rgba(0, 0, 0, 0.075);--bs-btn-disabled-opacity:0.65;--bs-btn-focus-box-shadow:0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color)}.btn-check+.btn:hover{color:var(--bs-btn-color);background-color:var(--bs-btn-bg);border-color:var(--bs-btn-border-color)}.btn:focus-visible{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:focus-visible+.btn{border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:checked+.btn,.btn.active,.btn.show,.btn:first-child:active,:not(.btn-check)+.btn:active{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color)}.btn-check:checked+.btn:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible,.btn:first-child:active:focus-visible,:not(.btn-check)+.btn:active:focus-visible{box-shadow:var(--bs-btn-focus-box-shadow)}.btn.disabled,.btn:disabled,fieldset:disabled .btn{color:var(--bs-btn-disabled-color);pointer-events:none;background-color:var(--bs-btn-disabled-bg);border-color:var(--bs-btn-disabled-border-color);opacity:var(--bs-btn-disabled-opacity)}.btn-primary{--bs-btn-color:#fff;--bs-btn-bg:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#0b5ed7;--bs-btn-hover-border-color:#0a58ca;--bs-btn-focus-shadow-rgb:49,132,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:#0a58ca;--bs-btn-active-border-color:#0a53be;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#0d6efd;--bs-btn-disabled-border-color:#0d6efd}.btn-secondary{--bs-btn-color:#fff;--bs-btn-bg:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#5c636a;--bs-btn-hover-border-color:#565e64;--bs-btn-focus-shadow-rgb:130,138,145;--bs-btn-active-color:#fff;--bs-btn-active-bg:#565e64;--bs-btn-active-border-color:#51585e;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#6c757d;--bs-btn-disabled-border-color:#6c757d}.btn-success{--bs-btn-color:#fff;--bs-btn-bg:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#157347;--bs-btn-hover-border-color:#146c43;--bs-btn-focus-shadow-rgb:60,153,110;--bs-btn-active-color:#fff;--bs-btn-active-bg:#146c43;--bs-btn-active-border-color:#13653f;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#198754;--bs-btn-disabled-border-color:#198754}.btn-info{--bs-btn-color:#000;--bs-btn-bg:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#31d2f2;--bs-btn-hover-border-color:#25cff2;--bs-btn-focus-shadow-rgb:11,172,204;--bs-btn-active-color:#000;--bs-btn-active-bg:#3dd5f3;--bs-btn-active-border-color:#25cff2;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#0dcaf0;--bs-btn-disabled-border-color:#0dcaf0}.btn-warning{--bs-btn-color:#000;--bs-btn-bg:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ffca2c;--bs-btn-hover-border-color:#ffc720;--bs-btn-focus-shadow-rgb:217,164,6;--bs-btn-active-color:#000;--bs-btn-active-bg:#ffcd39;--bs-btn-active-border-color:#ffc720;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#ffc107;--bs-btn-disabled-border-color:#ffc107}.btn-danger{--bs-btn-color:#fff;--bs-btn-bg:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#bb2d3b;--bs-btn-hover-border-color:#b02a37;--bs-btn-focus-shadow-rgb:225,83,97;--bs-btn-active-color:#fff;--bs-btn-active-bg:#b02a37;--bs-btn-active-border-color:#a52834;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#dc3545;--bs-btn-disabled-border-color:#dc3545}.btn-light{--bs-btn-color:#000;--bs-btn-bg:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#d3d4d5;--bs-btn-hover-border-color:#c6c7c8;--bs-btn-focus-shadow-rgb:211,212,213;--bs-btn-active-color:#000;--bs-btn-active-bg:#c6c7c8;--bs-btn-active-border-color:#babbbc;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#f8f9fa;--bs-btn-disabled-border-color:#f8f9fa}.btn-dark{--bs-btn-color:#fff;--bs-btn-bg:#212529;--bs-btn-border-color:#212529;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#424649;--bs-btn-hover-border-color:#373b3e;--bs-btn-focus-shadow-rgb:66,70,73;--bs-btn-active-color:#fff;--bs-btn-active-bg:#4d5154;--bs-btn-active-border-color:#373b3e;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#212529;--bs-btn-disabled-border-color:#212529}.btn-outline-primary{--bs-btn-color:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#0d6efd;--bs-btn-hover-border-color:#0d6efd;--bs-btn-focus-shadow-rgb:13,110,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:#0d6efd;--bs-btn-active-border-color:#0d6efd;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#0d6efd;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#0d6efd;--bs-gradient:none}.btn-outline-secondary{--bs-btn-color:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#6c757d;--bs-btn-hover-border-color:#6c757d;--bs-btn-focus-shadow-rgb:108,117,125;--bs-btn-active-color:#fff;--bs-btn-active-bg:#6c757d;--bs-btn-active-border-color:#6c757d;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#6c757d;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#6c757d;--bs-gradient:none}.btn-outline-success{--bs-btn-color:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#198754;--bs-btn-hover-border-color:#198754;--bs-btn-focus-shadow-rgb:25,135,84;--bs-btn-active-color:#fff;--bs-btn-active-bg:#198754;--bs-btn-active-border-color:#198754;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#198754;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#198754;--bs-gradient:none}.btn-outline-info{--bs-btn-color:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#0dcaf0;--bs-btn-hover-border-color:#0dcaf0;--bs-btn-focus-shadow-rgb:13,202,240;--bs-btn-active-color:#000;--bs-btn-active-bg:#0dcaf0;--bs-btn-active-border-color:#0dcaf0;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#0dcaf0;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#0dcaf0;--bs-gradient:none}.btn-outline-warning{--bs-btn-color:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ffc107;--bs-btn-hover-border-color:#ffc107;--bs-btn-focus-shadow-rgb:255,193,7;--bs-btn-active-color:#000;--bs-btn-active-bg:#ffc107;--bs-btn-active-border-color:#ffc107;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#ffc107;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#ffc107;--bs-gradient:none}.btn-outline-danger{--bs-btn-color:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#dc3545;--bs-btn-hover-border-color:#dc3545;--bs-btn-focus-shadow-rgb:220,53,69;--bs-btn-active-color:#fff;--bs-btn-active-bg:#dc3545;--bs-btn-active-border-color:#dc3545;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#dc3545;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#dc3545;--bs-gradient:none}.btn-outline-light{--bs-btn-color:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#f8f9fa;--bs-btn-hover-border-color:#f8f9fa;--bs-btn-focus-shadow-rgb:248,249,250;--bs-btn-active-color:#000;--bs-btn-active-bg:#f8f9fa;--bs-btn-active-border-color:#f8f9fa;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#f8f9fa;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#f8f9fa;--bs-gradient:none}.btn-outline-dark{--bs-btn-color:#212529;--bs-btn-border-color:#212529;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#212529;--bs-btn-hover-border-color:#212529;--bs-btn-focus-shadow-rgb:33,37,41;--bs-btn-active-color:#fff;--bs-btn-active-bg:#212529;--bs-btn-active-border-color:#212529;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#212529;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#212529;--bs-gradient:none}.btn-link{--bs-btn-font-weight:400;--bs-btn-color:var(--bs-link-color);--bs-btn-bg:transparent;--bs-btn-border-color:transparent;--bs-btn-hover-color:var(--bs-link-hover-color);--bs-btn-hover-border-color:transparent;--bs-btn-active-color:var(--bs-link-hover-color);--bs-btn-active-border-color:transparent;--bs-btn-disabled-color:#6c757d;--bs-btn-disabled-border-color:transparent;--bs-btn-box-shadow:none;--bs-btn-focus-shadow-rgb:49,132,253;text-decoration:underline}.btn-link:focus-visible{color:var(--bs-btn-color)}.btn-link:hover{color:var(--bs-btn-hover-color)}.btn-group-lg>.btn,.btn-lg{--bs-btn-padding-y:0.5rem;--bs-btn-padding-x:1rem;--bs-btn-font-size:1.25rem;--bs-btn-border-radius:0.5rem}.btn-group-sm>.btn,.btn-sm{--bs-btn-padding-y:0.25rem;--bs-btn-padding-x:0.5rem;--bs-btn-font-size:0.875rem;--bs-btn-border-radius:0.25rem}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.collapse-horizontal{transition:none}}.dropdown,.dropdown-center,.dropend,.dropstart,.dropup,.dropup-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{--bs-dropdown-zindex:1000;--bs-dropdown-min-width:10rem;--bs-dropdown-padding-x:0;--bs-dropdown-padding-y:0.5rem;--bs-dropdown-spacer:0.125rem;--bs-dropdown-font-size:1rem;--bs-dropdown-color:#212529;--bs-dropdown-bg:#fff;--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-border-radius:0.375rem;--bs-dropdown-border-width:1px;--bs-dropdown-inner-border-radius:calc(0.375rem - 1px);--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-divider-margin-y:0.5rem;--bs-dropdown-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-dropdown-link-color:#212529;--bs-dropdown-link-hover-color:#1e2125;--bs-dropdown-link-hover-bg:#e9ecef;--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#0d6efd;--bs-dropdown-link-disabled-color:#adb5bd;--bs-dropdown-item-padding-x:1rem;--bs-dropdown-item-padding-y:0.25rem;--bs-dropdown-header-color:#6c757d;--bs-dropdown-header-padding-x:1rem;--bs-dropdown-header-padding-y:0.5rem;position:absolute;z-index:var(--bs-dropdown-zindex);display:none;min-width:var(--bs-dropdown-min-width);padding:var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x);margin:0;font-size:var(--bs-dropdown-font-size);color:var(--bs-dropdown-color);text-align:left;list-style:none;background-color:var(--bs-dropdown-bg);background-clip:padding-box;border:var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color);border-radius:var(--bs-dropdown-border-radius)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:var(--bs-dropdown-spacer)}.dropdown-menu-start{--bs-position:start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position:end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-start{--bs-position:start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position:end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-start{--bs-position:start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position:end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-start{--bs-position:start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position:end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-start{--bs-position:start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position:end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1400px){.dropdown-menu-xxl-start{--bs-position:start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position:end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:var(--bs-dropdown-spacer)}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:var(--bs-dropdown-spacer)}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:var(--bs-dropdown-spacer)}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:var(--bs-dropdown-divider-margin-y) 0;overflow:hidden;border-top:1px solid var(--bs-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--bs-dropdown-link-color);text-align:inherit;text-decoration:none;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-item:active{color:var(--bs-dropdown-link-active-color);text-decoration:none;background-color:var(--bs-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-item:disabled{color:var(--bs-dropdown-link-disabled-color);pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x);margin-bottom:0;font-size:.875rem;color:var(--bs-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);color:var(--bs-dropdown-link-color)}.dropdown-menu-dark{--bs-dropdown-color:#dee2e6;--bs-dropdown-bg:#343a40;--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-box-shadow: ;--bs-dropdown-link-color:#dee2e6;--bs-dropdown-link-hover-color:#fff;--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-link-hover-bg:rgba(255, 255, 255, 0.15);--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#0d6efd;--bs-dropdown-link-disabled-color:#adb5bd;--bs-dropdown-header-color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group{border-radius:.375rem}.btn-group>.btn-group:not(:first-child),.btn-group>:not(.btn-check:first-child)+.btn{margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn.dropdown-toggle-split:first-child,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn~.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{--bs-nav-link-padding-x:1rem;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-link-color);--bs-nav-link-hover-color:var(--bs-link-hover-color);--bs-nav-link-disabled-color:#6c757d;display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);color:var(--bs-nav-link-color);text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:var(--bs-nav-link-hover-color)}.nav-link.disabled{color:var(--bs-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--bs-nav-tabs-border-width:1px;--bs-nav-tabs-border-color:#dee2e6;--bs-nav-tabs-border-radius:0.375rem;--bs-nav-tabs-link-hover-border-color:#e9ecef #e9ecef #dee2e6;--bs-nav-tabs-link-active-color:#495057;--bs-nav-tabs-link-active-bg:#fff;--bs-nav-tabs-link-active-border-color:#dee2e6 #dee2e6 #fff;border-bottom:var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color)}.nav-tabs .nav-link{margin-bottom:calc(-1 * var(--bs-nav-tabs-border-width));background:0 0;border:var(--bs-nav-tabs-border-width) solid transparent;border-top-left-radius:var(--bs-nav-tabs-border-radius);border-top-right-radius:var(--bs-nav-tabs-border-radius)}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{isolation:isolate;border-color:var(--bs-nav-tabs-link-hover-border-color)}.nav-tabs .nav-link.disabled,.nav-tabs .nav-link:disabled{color:var(--bs-nav-link-disabled-color);background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:var(--bs-nav-tabs-link-active-color);background-color:var(--bs-nav-tabs-link-active-bg);border-color:var(--bs-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1 * var(--bs-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--bs-nav-pills-border-radius:0.375rem;--bs-nav-pills-link-active-color:#fff;--bs-nav-pills-link-active-bg:#0d6efd}.nav-pills .nav-link{background:0 0;border:0;border-radius:var(--bs-nav-pills-border-radius)}.nav-pills .nav-link:disabled{color:var(--bs-nav-link-disabled-color);background-color:transparent;border-color:transparent}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--bs-nav-pills-link-active-color);background-color:var(--bs-nav-pills-link-active-bg)}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x:0;--bs-navbar-padding-y:0.5rem;--bs-navbar-color:rgba(0, 0, 0, 0.55);--bs-navbar-hover-color:rgba(0, 0, 0, 0.7);--bs-navbar-disabled-color:rgba(0, 0, 0, 0.3);--bs-navbar-active-color:rgba(0, 0, 0, 0.9);--bs-navbar-brand-padding-y:0.3125rem;--bs-navbar-brand-margin-end:1rem;--bs-navbar-brand-font-size:1.25rem;--bs-navbar-brand-color:rgba(0, 0, 0, 0.9);--bs-navbar-brand-hover-color:rgba(0, 0, 0, 0.9);--bs-navbar-nav-link-padding-x:0.5rem;--bs-navbar-toggler-padding-y:0.25rem;--bs-navbar-toggler-padding-x:0.75rem;--bs-navbar-toggler-font-size:1.25rem;--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--bs-navbar-toggler-border-color:rgba(0, 0, 0, 0.1);--bs-navbar-toggler-border-radius:0.375rem;--bs-navbar-toggler-focus-width:0.25rem;--bs-navbar-toggler-transition:box-shadow 0.15s ease-in-out;position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:var(--bs-navbar-padding-y) var(--bs-navbar-padding-x)}.navbar>.container,.navbar>.container-fluid,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:var(--bs-navbar-brand-padding-y);padding-bottom:var(--bs-navbar-brand-padding-y);margin-right:var(--bs-navbar-brand-margin-end);font-size:var(--bs-navbar-brand-font-size);color:var(--bs-navbar-brand-color);text-decoration:none;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x:0;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-navbar-color);--bs-nav-link-hover-color:var(--bs-navbar-hover-color);--bs-nav-link-disabled-color:var(--bs-navbar-disabled-color);display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link.active,.navbar-nav .show>.nav-link{color:var(--bs-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-navbar-color)}.navbar-text a,.navbar-text a:focus,.navbar-text a:hover{color:var(--bs-navbar-active-color)}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);font-size:var(--bs-navbar-toggler-font-size);line-height:1;color:var(--bs-navbar-color);background-color:transparent;border:var(--bs-border-width) solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);transition:var(--bs-navbar-toggler-transition)}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--bs-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height,75vh);overflow-y:auto}@media (min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-sm .offcanvas .offcanvas-header{display:none}.navbar-expand-sm .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-md .offcanvas .offcanvas-header{display:none}.navbar-expand-md .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-xl .offcanvas .offcanvas-header{display:none}.navbar-expand-xl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-xxl .offcanvas .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand .offcanvas .offcanvas-header{display:none}.navbar-expand .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}.navbar-dark{--bs-navbar-color:rgba(255, 255, 255, 0.55);--bs-navbar-hover-color:rgba(255, 255, 255, 0.75);--bs-navbar-disabled-color:rgba(255, 255, 255, 0.25);--bs-navbar-active-color:#fff;--bs-navbar-brand-color:#fff;--bs-navbar-brand-hover-color:#fff;--bs-navbar-toggler-border-color:rgba(255, 255, 255, 0.1);--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--bs-card-spacer-y:1rem;--bs-card-spacer-x:1rem;--bs-card-title-spacer-y:0.5rem;--bs-card-border-width:1px;--bs-card-border-color:var(--bs-border-color-translucent);--bs-card-border-radius:0.375rem;--bs-card-box-shadow: ;--bs-card-inner-border-radius:calc(0.375rem - 1px);--bs-card-cap-padding-y:0.5rem;--bs-card-cap-padding-x:1rem;--bs-card-cap-bg:rgba(0, 0, 0, 0.03);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg:#fff;--bs-card-img-overlay-padding:1rem;--bs-card-group-margin:0.75rem;position:relative;display:flex;flex-direction:column;min-width:0;height:var(--bs-card-height);word-wrap:break-word;background-color:var(--bs-card-bg);background-clip:border-box;border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius)}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x);color:var(--bs-card-color)}.card-title{margin-bottom:var(--bs-card-title-spacer-y)}.card-subtitle{margin-top:calc(-.5 * var(--bs-card-title-spacer-y));margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:var(--bs-card-spacer-x)}.card-header{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);margin-bottom:0;color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-bottom:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-header:first-child{border-radius:var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0}.card-footer{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-top:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-footer:last-child{border-radius:0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius)}.card-header-tabs{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-bottom:calc(-1 * var(--bs-card-cap-padding-y));margin-left:calc(-.5 * var(--bs-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active{background-color:var(--bs-card-bg);border-bottom-color:var(--bs-card-bg)}.card-header-pills{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-left:calc(-.5 * var(--bs-card-cap-padding-x))}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:var(--bs-card-img-overlay-padding);border-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom,.card-img-top{width:100%}.card-img,.card-img-top{border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom{border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card-group>.card{margin-bottom:var(--bs-card-group-margin)}@media (min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.accordion{--bs-accordion-color:#212529;--bs-accordion-bg:#fff;--bs-accordion-transition:color 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out,border-radius 0.15s ease;--bs-accordion-border-color:var(--bs-border-color);--bs-accordion-border-width:1px;--bs-accordion-border-radius:0.375rem;--bs-accordion-inner-border-radius:calc(0.375rem - 1px);--bs-accordion-btn-padding-x:1.25rem;--bs-accordion-btn-padding-y:1rem;--bs-accordion-btn-color:#212529;--bs-accordion-btn-bg:var(--bs-accordion-bg);--bs-accordion-btn-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-icon-width:1.25rem;--bs-accordion-btn-icon-transform:rotate(-180deg);--bs-accordion-btn-icon-transition:transform 0.2s ease-in-out;--bs-accordion-btn-active-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-focus-border-color:#86b7fe;--bs-accordion-btn-focus-box-shadow:0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-accordion-body-padding-x:1.25rem;--bs-accordion-body-padding-y:1rem;--bs-accordion-active-color:#0c63e4;--bs-accordion-active-bg:#e7f1ff}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x);font-size:1rem;color:var(--bs-accordion-btn-color);text-align:left;background-color:var(--bs-accordion-btn-bg);border:0;border-radius:0;overflow-anchor:none;transition:var(--bs-accordion-transition)}@media (prefers-reduced-motion:reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:var(--bs-accordion-active-color);background-color:var(--bs-accordion-active-bg);box-shadow:inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color)}.accordion-button:not(.collapsed)::after{background-image:var(--bs-accordion-btn-active-icon);transform:var(--bs-accordion-btn-icon-transform)}.accordion-button::after{flex-shrink:0;width:var(--bs-accordion-btn-icon-width);height:var(--bs-accordion-btn-icon-width);margin-left:auto;content:"";background-image:var(--bs-accordion-btn-icon);background-repeat:no-repeat;background-size:var(--bs-accordion-btn-icon-width);transition:var(--bs-accordion-btn-icon-transition)}@media (prefers-reduced-motion:reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:var(--bs-accordion-btn-focus-border-color);outline:0;box-shadow:var(--bs-accordion-btn-focus-box-shadow)}.accordion-header{margin-bottom:0}.accordion-item{color:var(--bs-accordion-color);background-color:var(--bs-accordion-bg);border:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.accordion-item:first-of-type{border-top-left-radius:var(--bs-accordion-border-radius);border-top-right-radius:var(--bs-accordion-border-radius)}.accordion-item:first-of-type .accordion-button{border-top-left-radius:var(--bs-accordion-inner-border-radius);border-top-right-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-right-radius:var(--bs-accordion-inner-border-radius);border-bottom-left-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:last-of-type .accordion-collapse{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-body{padding:var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x)}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.accordion-flush .accordion-item .accordion-button,.accordion-flush .accordion-item .accordion-button.collapsed{border-radius:0}.breadcrumb{--bs-breadcrumb-padding-x:0;--bs-breadcrumb-padding-y:0;--bs-breadcrumb-margin-bottom:1rem;--bs-breadcrumb-bg: ;--bs-breadcrumb-border-radius: ;--bs-breadcrumb-divider-color:#6c757d;--bs-breadcrumb-item-padding-x:0.5rem;--bs-breadcrumb-item-active-color:#6c757d;display:flex;flex-wrap:wrap;padding:var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x);margin-bottom:var(--bs-breadcrumb-margin-bottom);font-size:var(--bs-breadcrumb-font-size);list-style:none;background-color:var(--bs-breadcrumb-bg);border-radius:var(--bs-breadcrumb-border-radius)}.breadcrumb-item+.breadcrumb-item{padding-left:var(--bs-breadcrumb-item-padding-x)}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:var(--bs-breadcrumb-item-padding-x);color:var(--bs-breadcrumb-divider-color);content:var(--bs-breadcrumb-divider, "/")}.breadcrumb-item.active{color:var(--bs-breadcrumb-item-active-color)}.pagination{--bs-pagination-padding-x:0.75rem;--bs-pagination-padding-y:0.375rem;--bs-pagination-font-size:1rem;--bs-pagination-color:var(--bs-link-color);--bs-pagination-bg:#fff;--bs-pagination-border-width:1px;--bs-pagination-border-color:#dee2e6;--bs-pagination-border-radius:0.375rem;--bs-pagination-hover-color:var(--bs-link-hover-color);--bs-pagination-hover-bg:#e9ecef;--bs-pagination-hover-border-color:#dee2e6;--bs-pagination-focus-color:var(--bs-link-hover-color);--bs-pagination-focus-bg:#e9ecef;--bs-pagination-focus-box-shadow:0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-pagination-active-color:#fff;--bs-pagination-active-bg:#0d6efd;--bs-pagination-active-border-color:#0d6efd;--bs-pagination-disabled-color:#6c757d;--bs-pagination-disabled-bg:#fff;--bs-pagination-disabled-border-color:#dee2e6;display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;padding:var(--bs-pagination-padding-y) var(--bs-pagination-padding-x);font-size:var(--bs-pagination-font-size);color:var(--bs-pagination-color);text-decoration:none;background-color:var(--bs-pagination-bg);border:var(--bs-pagination-border-width) solid var(--bs-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--bs-pagination-hover-color);background-color:var(--bs-pagination-hover-bg);border-color:var(--bs-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--bs-pagination-focus-color);background-color:var(--bs-pagination-focus-bg);outline:0;box-shadow:var(--bs-pagination-focus-box-shadow)}.active>.page-link,.page-link.active{z-index:3;color:var(--bs-pagination-active-color);background-color:var(--bs-pagination-active-bg);border-color:var(--bs-pagination-active-border-color)}.disabled>.page-link,.page-link.disabled{color:var(--bs-pagination-disabled-color);pointer-events:none;background-color:var(--bs-pagination-disabled-bg);border-color:var(--bs-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:-1px}.page-item:first-child .page-link{border-top-left-radius:var(--bs-pagination-border-radius);border-bottom-left-radius:var(--bs-pagination-border-radius)}.page-item:last-child .page-link{border-top-right-radius:var(--bs-pagination-border-radius);border-bottom-right-radius:var(--bs-pagination-border-radius)}.pagination-lg{--bs-pagination-padding-x:1.5rem;--bs-pagination-padding-y:0.75rem;--bs-pagination-font-size:1.25rem;--bs-pagination-border-radius:0.5rem}.pagination-sm{--bs-pagination-padding-x:0.5rem;--bs-pagination-padding-y:0.25rem;--bs-pagination-font-size:0.875rem;--bs-pagination-border-radius:0.25rem}.badge{--bs-badge-padding-x:0.65em;--bs-badge-padding-y:0.35em;--bs-badge-font-size:0.75em;--bs-badge-font-weight:700;--bs-badge-color:#fff;--bs-badge-border-radius:0.375rem;display:inline-block;padding:var(--bs-badge-padding-y) var(--bs-badge-padding-x);font-size:var(--bs-badge-font-size);font-weight:var(--bs-badge-font-weight);line-height:1;color:var(--bs-badge-color);text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:var(--bs-badge-border-radius)}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{--bs-alert-bg:transparent;--bs-alert-padding-x:1rem;--bs-alert-padding-y:1rem;--bs-alert-margin-bottom:1rem;--bs-alert-color:inherit;--bs-alert-border-color:transparent;--bs-alert-border:1px solid var(--bs-alert-border-color);--bs-alert-border-radius:0.375rem;position:relative;padding:var(--bs-alert-padding-y) var(--bs-alert-padding-x);margin-bottom:var(--bs-alert-margin-bottom);color:var(--bs-alert-color);background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius)}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-primary{--bs-alert-color:#084298;--bs-alert-bg:#cfe2ff;--bs-alert-border-color:#b6d4fe}.alert-primary .alert-link{color:#06357a}.alert-secondary{--bs-alert-color:#41464b;--bs-alert-bg:#e2e3e5;--bs-alert-border-color:#d3d6d8}.alert-secondary .alert-link{color:#34383c}.alert-success{--bs-alert-color:#0f5132;--bs-alert-bg:#d1e7dd;--bs-alert-border-color:#badbcc}.alert-success .alert-link{color:#0c4128}.alert-info{--bs-alert-color:#055160;--bs-alert-bg:#cff4fc;--bs-alert-border-color:#b6effb}.alert-info .alert-link{color:#04414d}.alert-warning{--bs-alert-color:#664d03;--bs-alert-bg:#fff3cd;--bs-alert-border-color:#ffecb5}.alert-warning .alert-link{color:#523e02}.alert-danger{--bs-alert-color:#842029;--bs-alert-bg:#f8d7da;--bs-alert-border-color:#f5c2c7}.alert-danger .alert-link{color:#6a1a21}.alert-light{--bs-alert-color:#636464;--bs-alert-bg:#fefefe;--bs-alert-border-color:#fdfdfe}.alert-light .alert-link{color:#4f5050}.alert-dark{--bs-alert-color:#141619;--bs-alert-bg:#d3d3d4;--bs-alert-border-color:#bcbebf}.alert-dark .alert-link{color:#101214}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress{--bs-progress-height:1rem;--bs-progress-font-size:0.75rem;--bs-progress-bg:#e9ecef;--bs-progress-border-radius:0.375rem;--bs-progress-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-progress-bar-color:#fff;--bs-progress-bar-bg:#0d6efd;--bs-progress-bar-transition:width 0.6s ease;display:flex;height:var(--bs-progress-height);overflow:hidden;font-size:var(--bs-progress-font-size);background-color:var(--bs-progress-bg);border-radius:var(--bs-progress-border-radius)}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:var(--bs-progress-bar-color);text-align:center;white-space:nowrap;background-color:var(--bs-progress-bar-bg);transition:var(--bs-progress-bar-transition)}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:var(--bs-progress-height) var(--bs-progress-height)}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.list-group{--bs-list-group-color:#212529;--bs-list-group-bg:#fff;--bs-list-group-border-color:rgba(0, 0, 0, 0.125);--bs-list-group-border-width:1px;--bs-list-group-border-radius:0.375rem;--bs-list-group-item-padding-x:1rem;--bs-list-group-item-padding-y:0.5rem;--bs-list-group-action-color:#495057;--bs-list-group-action-hover-color:#495057;--bs-list-group-action-hover-bg:#f8f9fa;--bs-list-group-action-active-color:#212529;--bs-list-group-action-active-bg:#e9ecef;--bs-list-group-disabled-color:#6c757d;--bs-list-group-disabled-bg:#fff;--bs-list-group-active-color:#fff;--bs-list-group-active-bg:#0d6efd;--bs-list-group-active-border-color:#0d6efd;display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:var(--bs-list-group-border-radius)}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>.list-group-item::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item-action{width:100%;color:var(--bs-list-group-action-color);text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:var(--bs-list-group-action-hover-color);text-decoration:none;background-color:var(--bs-list-group-action-hover-bg)}.list-group-item-action:active{color:var(--bs-list-group-action-active-color);background-color:var(--bs-list-group-action-active-bg)}.list-group-item{position:relative;display:block;padding:var(--bs-list-group-item-padding-y) var(--bs-list-group-item-padding-x);color:var(--bs-list-group-color);text-decoration:none;background-color:var(--bs-list-group-bg);border:var(--bs-list-group-border-width) solid var(--bs-list-group-border-color)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:var(--bs-list-group-disabled-color);pointer-events:none;background-color:var(--bs-list-group-disabled-bg)}.list-group-item.active{z-index:2;color:var(--bs-list-group-active-color);background-color:var(--bs-list-group-active-bg);border-color:var(--bs-list-group-active-border-color)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:calc(-1 * var(--bs-list-group-border-width));border-top-width:var(--bs-list-group-border-width)}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}@media (min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 var(--bs-list-group-border-width)}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#084298;background-color:#cfe2ff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#084298;background-color:#bacbe6}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#084298;border-color:#084298}.list-group-item-secondary{color:#41464b;background-color:#e2e3e5}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#41464b;background-color:#cbccce}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#41464b;border-color:#41464b}.list-group-item-success{color:#0f5132;background-color:#d1e7dd}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#0f5132;background-color:#bcd0c7}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#0f5132;border-color:#0f5132}.list-group-item-info{color:#055160;background-color:#cff4fc}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#055160;background-color:#badce3}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#055160;border-color:#055160}.list-group-item-warning{color:#664d03;background-color:#fff3cd}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#664d03;background-color:#e6dbb9}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#664d03;border-color:#664d03}.list-group-item-danger{color:#842029;background-color:#f8d7da}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#842029;background-color:#dfc2c4}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#842029;border-color:#842029}.list-group-item-light{color:#636464;background-color:#fefefe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#636464;background-color:#e5e5e5}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#636464;border-color:#636464}.list-group-item-dark{color:#141619;background-color:#d3d3d4}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#141619;background-color:#bebebf}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#141619;border-color:#141619}.btn-close{box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:#000;background:transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat;border:0;border-radius:.375rem;opacity:.5}.btn-close:hover{color:#000;text-decoration:none;opacity:.75}.btn-close:focus{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25);opacity:1}.btn-close.disabled,.btn-close:disabled{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;opacity:.25}.btn-close-white{filter:invert(1) grayscale(100%) brightness(200%)}.toast{--bs-toast-zindex:1090;--bs-toast-padding-x:0.75rem;--bs-toast-padding-y:0.5rem;--bs-toast-spacing:1.5rem;--bs-toast-max-width:350px;--bs-toast-font-size:0.875rem;--bs-toast-color: ;--bs-toast-bg:rgba(255, 255, 255, 0.85);--bs-toast-border-width:1px;--bs-toast-border-color:var(--bs-border-color-translucent);--bs-toast-border-radius:0.375rem;--bs-toast-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-toast-header-color:#6c757d;--bs-toast-header-bg:rgba(255, 255, 255, 0.85);--bs-toast-header-border-color:rgba(0, 0, 0, 0.05);width:var(--bs-toast-max-width);max-width:100%;font-size:var(--bs-toast-font-size);color:var(--bs-toast-color);pointer-events:auto;background-color:var(--bs-toast-bg);background-clip:padding-box;border:var(--bs-toast-border-width) solid var(--bs-toast-border-color);box-shadow:var(--bs-toast-box-shadow);border-radius:var(--bs-toast-border-radius)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--bs-toast-zindex:1090;position:absolute;z-index:var(--bs-toast-zindex);width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--bs-toast-spacing)}.toast-header{display:flex;align-items:center;padding:var(--bs-toast-padding-y) var(--bs-toast-padding-x);color:var(--bs-toast-header-color);background-color:var(--bs-toast-header-bg);background-clip:padding-box;border-bottom:var(--bs-toast-border-width) solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width))}.toast-header .btn-close{margin-right:calc(-.5 * var(--bs-toast-padding-x));margin-left:var(--bs-toast-padding-x)}.toast-body{padding:var(--bs-toast-padding-x);word-wrap:break-word}.modal{--bs-modal-zindex:1055;--bs-modal-width:500px;--bs-modal-padding:1rem;--bs-modal-margin:0.5rem;--bs-modal-color: ;--bs-modal-bg:#fff;--bs-modal-border-color:var(--bs-border-color-translucent);--bs-modal-border-width:1px;--bs-modal-border-radius:0.5rem;--bs-modal-box-shadow:0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-modal-inner-border-radius:calc(0.5rem - 1px);--bs-modal-header-padding-x:1rem;--bs-modal-header-padding-y:1rem;--bs-modal-header-padding:1rem 1rem;--bs-modal-header-border-color:var(--bs-border-color);--bs-modal-header-border-width:1px;--bs-modal-title-line-height:1.5;--bs-modal-footer-gap:0.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color:var(--bs-border-color);--bs-modal-footer-border-width:1px;position:fixed;top:0;left:0;z-index:var(--bs-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--bs-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--bs-modal-margin) * 2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - var(--bs-modal-margin) * 2)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--bs-modal-color);pointer-events:auto;background-color:var(--bs-modal-bg);background-clip:padding-box;border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);outline:0}.modal-backdrop{--bs-backdrop-zindex:1050;--bs-backdrop-bg:#000;--bs-backdrop-opacity:0.5;position:fixed;top:0;left:0;z-index:var(--bs-backdrop-zindex);width:100vw;height:100vh;background-color:var(--bs-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--bs-backdrop-opacity)}.modal-header{display:flex;flex-shrink:0;align-items:center;justify-content:space-between;padding:var(--bs-modal-header-padding);border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--bs-modal-header-padding-y) * .5) calc(var(--bs-modal-header-padding-x) * .5);margin:calc(-.5 * var(--bs-modal-header-padding-y)) calc(-.5 * var(--bs-modal-header-padding-x)) calc(-.5 * var(--bs-modal-header-padding-y)) auto}.modal-title{margin-bottom:0;line-height:var(--bs-modal-title-line-height)}.modal-body{position:relative;flex:1 1 auto;padding:var(--bs-modal-padding)}.modal-footer{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * .5);background-color:var(--bs-modal-footer-bg);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-bottom-left-radius:var(--bs-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap) * .5)}@media (min-width:576px){.modal{--bs-modal-margin:1.75rem;--bs-modal-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15)}.modal-dialog{max-width:var(--bs-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--bs-modal-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{--bs-modal-width:800px}}@media (min-width:1200px){.modal-xl{--bs-modal-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-footer,.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media (max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-footer,.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media (max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-footer,.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media (max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-footer,.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media (max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-footer,.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media (max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-footer,.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--bs-tooltip-zindex:1080;--bs-tooltip-max-width:200px;--bs-tooltip-padding-x:0.5rem;--bs-tooltip-padding-y:0.25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:0.875rem;--bs-tooltip-color:#fff;--bs-tooltip-bg:#000;--bs-tooltip-border-radius:0.375rem;--bs-tooltip-opacity:0.9;--bs-tooltip-arrow-width:0.8rem;--bs-tooltip-arrow-height:0.4rem;z-index:var(--bs-tooltip-zindex);display:block;padding:var(--bs-tooltip-arrow-height);margin:var(--bs-tooltip-margin);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-tooltip-font-size);word-wrap:break-word;opacity:0}.tooltip.show{opacity:var(--bs-tooltip-opacity)}.tooltip .tooltip-arrow{display:block;width:var(--bs-tooltip-arrow-width);height:var(--bs-tooltip-arrow-height)}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow,.bs-tooltip-top .tooltip-arrow{bottom:0}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before,.bs-tooltip-top .tooltip-arrow::before{top:-1px;border-width:var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-top-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow,.bs-tooltip-end .tooltip-arrow{left:0;width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before,.bs-tooltip-end .tooltip-arrow::before{right:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-right-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow,.bs-tooltip-bottom .tooltip-arrow{top:0}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before,.bs-tooltip-bottom .tooltip-arrow::before{bottom:-1px;border-width:0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-bottom-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow,.bs-tooltip-start .tooltip-arrow{right:0;width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before,.bs-tooltip-start .tooltip-arrow::before{left:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) 0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-left-color:var(--bs-tooltip-bg)}.tooltip-inner{max-width:var(--bs-tooltip-max-width);padding:var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x);color:var(--bs-tooltip-color);text-align:center;background-color:var(--bs-tooltip-bg);border-radius:var(--bs-tooltip-border-radius)}.popover{--bs-popover-zindex:1070;--bs-popover-max-width:276px;--bs-popover-font-size:0.875rem;--bs-popover-bg:#fff;--bs-popover-border-width:1px;--bs-popover-border-color:var(--bs-border-color-translucent);--bs-popover-border-radius:0.5rem;--bs-popover-inner-border-radius:calc(0.5rem - 1px);--bs-popover-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-popover-header-padding-x:1rem;--bs-popover-header-padding-y:0.5rem;--bs-popover-header-font-size:1rem;--bs-popover-header-color: ;--bs-popover-header-bg:#f0f0f0;--bs-popover-body-padding-x:1rem;--bs-popover-body-padding-y:1rem;--bs-popover-body-color:#212529;--bs-popover-arrow-width:1rem;--bs-popover-arrow-height:0.5rem;--bs-popover-arrow-border:var(--bs-popover-border-color);z-index:var(--bs-popover-zindex);display:block;max-width:var(--bs-popover-max-width);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-popover-font-size);word-wrap:break-word;background-color:var(--bs-popover-bg);background-clip:padding-box;border:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-radius:var(--bs-popover-border-radius)}.popover .popover-arrow{display:block;width:var(--bs-popover-arrow-width);height:var(--bs-popover-arrow-height)}.popover .popover-arrow::after,.popover .popover-arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid;border-width:0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow,.bs-popover-top>.popover-arrow{bottom:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::after,.bs-popover-top>.popover-arrow::before{border-width:var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::before{bottom:0;border-top-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-top>.popover-arrow::after{bottom:var(--bs-popover-border-width);border-top-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow,.bs-popover-end>.popover-arrow{left:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::after,.bs-popover-end>.popover-arrow::before{border-width:calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::before{left:0;border-right-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-end>.popover-arrow::after{left:var(--bs-popover-border-width);border-right-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow,.bs-popover-bottom>.popover-arrow{top:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::before{border-width:0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::before{top:0;border-bottom-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::after{top:var(--bs-popover-border-width);border-bottom-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:var(--bs-popover-arrow-width);margin-left:calc(-.5 * var(--bs-popover-arrow-width));content:"";border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-header-bg)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow,.bs-popover-start>.popover-arrow{right:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::after,.bs-popover-start>.popover-arrow::before{border-width:calc(var(--bs-popover-arrow-width) * .5) 0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::before{right:0;border-left-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-start>.popover-arrow::after{right:var(--bs-popover-border-width);border-left-color:var(--bs-popover-bg)}.popover-header{padding:var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x);margin-bottom:0;font-size:var(--bs-popover-header-font-size);color:var(--bs-popover-header-color);background-color:var(--bs-popover-header-bg);border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-top-left-radius:var(--bs-popover-inner-border-radius);border-top-right-radius:var(--bs-popover-inner-border-radius)}.popover-header:empty{display:none}.popover-body{padding:var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x);color:var(--bs-popover-body-color)}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-end,.carousel-item-next:not(.carousel-item-start){transform:translateX(100%)}.active.carousel-item-start,.carousel-item-prev:not(.carousel-item-end){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%;list-style:none}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-next-icon,.carousel-dark .carousel-control-prev-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}.spinner-border,.spinner-grow{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-border-width:0.25em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-border;border:var(--bs-spinner-border-width) solid currentcolor;border-right-color:transparent}.spinner-border-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem;--bs-spinner-border-width:0.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-grow;background-color:currentcolor;opacity:0}.spinner-grow-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{--bs-spinner-animation-speed:1.5s}}.offcanvas,.offcanvas-lg,.offcanvas-md,.offcanvas-sm,.offcanvas-xl,.offcanvas-xxl{--bs-offcanvas-zindex:1045;--bs-offcanvas-width:400px;--bs-offcanvas-height:30vh;--bs-offcanvas-padding-x:1rem;--bs-offcanvas-padding-y:1rem;--bs-offcanvas-color: ;--bs-offcanvas-bg:#fff;--bs-offcanvas-border-width:1px;--bs-offcanvas-border-color:var(--bs-border-color-translucent);--bs-offcanvas-box-shadow:0 0.125rem 0.25rem rgba(0, 0, 0, 0.075)}@media (max-width:575.98px){.offcanvas-sm{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}}@media (max-width:575.98px) and (prefers-reduced-motion:reduce){.offcanvas-sm{transition:none}}@media (max-width:575.98px){.offcanvas-sm.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}}@media (max-width:575.98px){.offcanvas-sm.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}}@media (max-width:575.98px){.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}}@media (max-width:575.98px){.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}}@media (max-width:575.98px){.offcanvas-sm.show:not(.hiding),.offcanvas-sm.showing{transform:none}}@media (max-width:575.98px){.offcanvas-sm.hiding,.offcanvas-sm.show,.offcanvas-sm.showing{visibility:visible}}@media (min-width:576px){.offcanvas-sm{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:767.98px){.offcanvas-md{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}}@media (max-width:767.98px) and (prefers-reduced-motion:reduce){.offcanvas-md{transition:none}}@media (max-width:767.98px){.offcanvas-md.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}}@media (max-width:767.98px){.offcanvas-md.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}}@media (max-width:767.98px){.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}}@media (max-width:767.98px){.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}}@media (max-width:767.98px){.offcanvas-md.show:not(.hiding),.offcanvas-md.showing{transform:none}}@media (max-width:767.98px){.offcanvas-md.hiding,.offcanvas-md.show,.offcanvas-md.showing{visibility:visible}}@media (min-width:768px){.offcanvas-md{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:991.98px){.offcanvas-lg{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}}@media (max-width:991.98px) and (prefers-reduced-motion:reduce){.offcanvas-lg{transition:none}}@media (max-width:991.98px){.offcanvas-lg.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}}@media (max-width:991.98px){.offcanvas-lg.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}}@media (max-width:991.98px){.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}}@media (max-width:991.98px){.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}}@media (max-width:991.98px){.offcanvas-lg.show:not(.hiding),.offcanvas-lg.showing{transform:none}}@media (max-width:991.98px){.offcanvas-lg.hiding,.offcanvas-lg.show,.offcanvas-lg.showing{visibility:visible}}@media (min-width:992px){.offcanvas-lg{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1199.98px){.offcanvas-xl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}}@media (max-width:1199.98px) and (prefers-reduced-motion:reduce){.offcanvas-xl{transition:none}}@media (max-width:1199.98px){.offcanvas-xl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}}@media (max-width:1199.98px){.offcanvas-xl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}}@media (max-width:1199.98px){.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}}@media (max-width:1199.98px){.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}}@media (max-width:1199.98px){.offcanvas-xl.show:not(.hiding),.offcanvas-xl.showing{transform:none}}@media (max-width:1199.98px){.offcanvas-xl.hiding,.offcanvas-xl.show,.offcanvas-xl.showing{visibility:visible}}@media (min-width:1200px){.offcanvas-xl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1399.98px){.offcanvas-xxl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}}@media (max-width:1399.98px) and (prefers-reduced-motion:reduce){.offcanvas-xxl{transition:none}}@media (max-width:1399.98px){.offcanvas-xxl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}}@media (max-width:1399.98px){.offcanvas-xxl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}}@media (max-width:1399.98px){.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}}@media (max-width:1399.98px){.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}}@media (max-width:1399.98px){.offcanvas-xxl.show:not(.hiding),.offcanvas-xxl.showing{transform:none}}@media (max-width:1399.98px){.offcanvas-xxl.hiding,.offcanvas-xxl.show,.offcanvas-xxl.showing{visibility:visible}}@media (min-width:1400px){.offcanvas-xxl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}.offcanvas{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:transform .3s ease-in-out}@media (prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas.show:not(.hiding),.offcanvas.showing{transform:none}.offcanvas.hiding,.offcanvas.show,.offcanvas.showing{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;align-items:center;justify-content:space-between;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x)}.offcanvas-header .btn-close{padding:calc(var(--bs-offcanvas-padding-y) * .5) calc(var(--bs-offcanvas-padding-x) * .5);margin-top:calc(-.5 * var(--bs-offcanvas-padding-y));margin-right:calc(-.5 * var(--bs-offcanvas-padding-x));margin-bottom:calc(-.5 * var(--bs-offcanvas-padding-y))}.offcanvas-title{margin-bottom:0;line-height:1.5}.offcanvas-body{flex-grow:1;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);overflow-y:auto}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentcolor;opacity:.5}.placeholder.btn::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{-webkit-mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);-webkit-mask-size:200% 100%;mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{100%{-webkit-mask-position:-200% 0%;mask-position:-200% 0%}}.clearfix::after{display:block;clear:both;content:""}.text-bg-primary{color:#fff!important;background-color:RGBA(13,110,253,var(--bs-bg-opacity,1))!important}.text-bg-secondary{color:#fff!important;background-color:RGBA(108,117,125,var(--bs-bg-opacity,1))!important}.text-bg-success{color:#fff!important;background-color:RGBA(25,135,84,var(--bs-bg-opacity,1))!important}.text-bg-info{color:#000!important;background-color:RGBA(13,202,240,var(--bs-bg-opacity,1))!important}.text-bg-warning{color:#000!important;background-color:RGBA(255,193,7,var(--bs-bg-opacity,1))!important}.text-bg-danger{color:#fff!important;background-color:RGBA(220,53,69,var(--bs-bg-opacity,1))!important}.text-bg-light{color:#000!important;background-color:RGBA(248,249,250,var(--bs-bg-opacity,1))!important}.text-bg-dark{color:#fff!important;background-color:RGBA(33,37,41,var(--bs-bg-opacity,1))!important}.link-primary{color:#0d6efd!important}.link-primary:focus,.link-primary:hover{color:#0a58ca!important}.link-secondary{color:#6c757d!important}.link-secondary:focus,.link-secondary:hover{color:#565e64!important}.link-success{color:#198754!important}.link-success:focus,.link-success:hover{color:#146c43!important}.link-info{color:#0dcaf0!important}.link-info:focus,.link-info:hover{color:#3dd5f3!important}.link-warning{color:#ffc107!important}.link-warning:focus,.link-warning:hover{color:#ffcd39!important}.link-danger{color:#dc3545!important}.link-danger:focus,.link-danger:hover{color:#b02a37!important}.link-light{color:#f8f9fa!important}.link-light:focus,.link-light:hover{color:#f9fafb!important}.link-dark{color:#212529!important}.link-dark:focus,.link-dark:hover{color:#1a1e21!important}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio:100%}.ratio-4x3{--bs-aspect-ratio:75%}.ratio-16x9{--bs-aspect-ratio:56.25%}.ratio-21x9{--bs-aspect-ratio:42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}@media (min-width:576px){.sticky-sm-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:768px){.sticky-md-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:992px){.sticky-lg-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:1200px){.sticky-xl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:1400px){.sticky-xxl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}.hstack{display:flex;flex-direction:row;align-items:center;align-self:stretch}.vstack{display:flex;flex:1 1 auto;flex-direction:column;align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;width:1px;min-height:1em;background-color:currentcolor;opacity:.25}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.opacity-0{opacity:0!important}.opacity-25{opacity:.25!important}.opacity-50{opacity:.5!important}.opacity-75{opacity:.75!important}.opacity-100{opacity:1!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translateX(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-0{border:0!important}.border-top{border-top:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-top-0{border-top:0!important}.border-end{border-right:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-start-0{border-left:0!important}.border-primary{--bs-border-opacity:1;border-color:rgba(var(--bs-primary-rgb),var(--bs-border-opacity))!important}.border-secondary{--bs-border-opacity:1;border-color:rgba(var(--bs-secondary-rgb),var(--bs-border-opacity))!important}.border-success{--bs-border-opacity:1;border-color:rgba(var(--bs-success-rgb),var(--bs-border-opacity))!important}.border-info{--bs-border-opacity:1;border-color:rgba(var(--bs-info-rgb),var(--bs-border-opacity))!important}.border-warning{--bs-border-opacity:1;border-color:rgba(var(--bs-warning-rgb),var(--bs-border-opacity))!important}.border-danger{--bs-border-opacity:1;border-color:rgba(var(--bs-danger-rgb),var(--bs-border-opacity))!important}.border-light{--bs-border-opacity:1;border-color:rgba(var(--bs-light-rgb),var(--bs-border-opacity))!important}.border-dark{--bs-border-opacity:1;border-color:rgba(var(--bs-dark-rgb),var(--bs-border-opacity))!important}.border-white{--bs-border-opacity:1;border-color:rgba(var(--bs-white-rgb),var(--bs-border-opacity))!important}.border-1{--bs-border-width:1px}.border-2{--bs-border-width:2px}.border-3{--bs-border-width:3px}.border-4{--bs-border-width:4px}.border-5{--bs-border-width:5px}.border-opacity-10{--bs-border-opacity:0.1}.border-opacity-25{--bs-border-opacity:0.25}.border-opacity-50{--bs-border-opacity:0.5}.border-opacity-75{--bs-border-opacity:0.75}.border-opacity-100{--bs-border-opacity:1}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:1 1 auto!important}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.justify-content-evenly{justify-content:space-evenly!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:3rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:3rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:3rem!important}.ms-auto{margin-left:auto!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:3rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:3rem!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:3rem!important}.font-monospace{font-family:var(--bs-font-monospace)!important}.fs-1{font-size:calc(1.375rem + 1.5vw)!important}.fs-2{font-size:calc(1.325rem + .9vw)!important}.fs-3{font-size:calc(1.3rem + .6vw)!important}.fs-4{font-size:calc(1.275rem + .3vw)!important}.fs-5{font-size:1.25rem!important}.fs-6{font-size:1rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-light{font-weight:300!important}.fw-lighter{font-weight:lighter!important}.fw-normal{font-weight:400!important}.fw-bold{font-weight:700!important}.fw-semibold{font-weight:600!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.25!important}.lh-base{line-height:1.5!important}.lh-lg{line-height:2!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--bs-text-opacity:1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))!important}.text-secondary{--bs-text-opacity:1;color:rgba(var(--bs-secondary-rgb),var(--bs-text-opacity))!important}.text-success{--bs-text-opacity:1;color:rgba(var(--bs-success-rgb),var(--bs-text-opacity))!important}.text-info{--bs-text-opacity:1;color:rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important}.text-warning{--bs-text-opacity:1;color:rgba(var(--bs-warning-rgb),var(--bs-text-opacity))!important}.text-danger{--bs-text-opacity:1;color:rgba(var(--bs-danger-rgb),var(--bs-text-opacity))!important}.text-light{--bs-text-opacity:1;color:rgba(var(--bs-light-rgb),var(--bs-text-opacity))!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-black{--bs-text-opacity:1;color:rgba(var(--bs-black-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-body{--bs-text-opacity:1;color:rgba(var(--bs-body-color-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity:1;color:#6c757d!important}.text-black-50{--bs-text-opacity:1;color:rgba(0,0,0,.5)!important}.text-white-50{--bs-text-opacity:1;color:rgba(255,255,255,.5)!important}.text-reset{--bs-text-opacity:1;color:inherit!important}.text-opacity-25{--bs-text-opacity:0.25}.text-opacity-50{--bs-text-opacity:0.5}.text-opacity-75{--bs-text-opacity:0.75}.text-opacity-100{--bs-text-opacity:1}.bg-primary{--bs-bg-opacity:1;background-color:rgba(var(--bs-primary-rgb),var(--bs-bg-opacity))!important}.bg-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-rgb),var(--bs-bg-opacity))!important}.bg-success{--bs-bg-opacity:1;background-color:rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important}.bg-info{--bs-bg-opacity:1;background-color:rgba(var(--bs-info-rgb),var(--bs-bg-opacity))!important}.bg-warning{--bs-bg-opacity:1;background-color:rgba(var(--bs-warning-rgb),var(--bs-bg-opacity))!important}.bg-danger{--bs-bg-opacity:1;background-color:rgba(var(--bs-danger-rgb),var(--bs-bg-opacity))!important}.bg-light{--bs-bg-opacity:1;background-color:rgba(var(--bs-light-rgb),var(--bs-bg-opacity))!important}.bg-dark{--bs-bg-opacity:1;background-color:rgba(var(--bs-dark-rgb),var(--bs-bg-opacity))!important}.bg-black{--bs-bg-opacity:1;background-color:rgba(var(--bs-black-rgb),var(--bs-bg-opacity))!important}.bg-white{--bs-bg-opacity:1;background-color:rgba(var(--bs-white-rgb),var(--bs-bg-opacity))!important}.bg-body{--bs-bg-opacity:1;background-color:rgba(var(--bs-body-bg-rgb),var(--bs-bg-opacity))!important}.bg-transparent{--bs-bg-opacity:1;background-color:transparent!important}.bg-opacity-10{--bs-bg-opacity:0.1}.bg-opacity-25{--bs-bg-opacity:0.25}.bg-opacity-50{--bs-bg-opacity:0.5}.bg-opacity-75{--bs-bg-opacity:0.75}.bg-opacity-100{--bs-bg-opacity:1}.bg-gradient{background-image:var(--bs-gradient)!important}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:var(--bs-border-radius)!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:var(--bs-border-radius-sm)!important}.rounded-2{border-radius:var(--bs-border-radius)!important}.rounded-3{border-radius:var(--bs-border-radius-lg)!important}.rounded-4{border-radius:var(--bs-border-radius-xl)!important}.rounded-5{border-radius:var(--bs-border-radius-2xl)!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:var(--bs-border-radius-pill)!important}.rounded-top{border-top-left-radius:var(--bs-border-radius)!important;border-top-right-radius:var(--bs-border-radius)!important}.rounded-end{border-top-right-radius:var(--bs-border-radius)!important;border-bottom-right-radius:var(--bs-border-radius)!important}.rounded-bottom{border-bottom-right-radius:var(--bs-border-radius)!important;border-bottom-left-radius:var(--bs-border-radius)!important}.rounded-start{border-bottom-left-radius:var(--bs-border-radius)!important;border-top-left-radius:var(--bs-border-radius)!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media (min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.justify-content-sm-evenly{justify-content:space-evenly!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:3rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:3rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:3rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:3rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:3rem!important}.ms-sm-auto{margin-left:auto!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:3rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:3rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:3rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:3rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:3rem!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:3rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.justify-content-md-evenly{justify-content:space-evenly!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:3rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:3rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:3rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:3rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:3rem!important}.ms-md-auto{margin-left:auto!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:3rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:3rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:3rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:3rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:3rem!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:3rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.justify-content-lg-evenly{justify-content:space-evenly!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:3rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:3rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:3rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:3rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:3rem!important}.ms-lg-auto{margin-left:auto!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:3rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:3rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:3rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:3rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:3rem!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:3rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.justify-content-xl-evenly{justify-content:space-evenly!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:3rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:3rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:3rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:3rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:3rem!important}.ms-xl-auto{margin-left:auto!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:3rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:3rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:3rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:3rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:3rem!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:3rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}}@media (min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:1 1 auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:3rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:3rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:3rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:3rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:3rem!important}.ms-xxl-auto{margin-left:auto!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:3rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:3rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:3rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:3rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:3rem!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:3rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}}@media (min-width:1200px){.fs-1{font-size:2.5rem!important}.fs-2{font-size:2rem!important}.fs-3{font-size:1.75rem!important}.fs-4{font-size:1.5rem!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/django/static/bootstrap.min.css.map b/django/static/bootstrap.min.css.map new file mode 100644 index 0000000..336fa28 --- /dev/null +++ b/django/static/bootstrap.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/mixins/_banner.scss","../../scss/_root.scss","../../scss/vendor/_rfs.scss","../../scss/_reboot.scss","dist/css/bootstrap.css","../../scss/mixins/_border-radius.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/_containers.scss","../../scss/mixins/_container.scss","../../scss/mixins/_breakpoints.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/_tables.scss","../../scss/mixins/_table-variants.scss","../../scss/forms/_labels.scss","../../scss/forms/_form-text.scss","../../scss/forms/_form-control.scss","../../scss/mixins/_transition.scss","../../scss/mixins/_gradients.scss","../../scss/forms/_form-select.scss","../../scss/forms/_form-check.scss","../../scss/forms/_form-range.scss","../../scss/forms/_floating-labels.scss","../../scss/forms/_input-group.scss","../../scss/mixins/_forms.scss","../../scss/_buttons.scss","../../scss/mixins/_buttons.scss","../../scss/_transitions.scss","../../scss/_dropdown.scss","../../scss/mixins/_caret.scss","../../scss/_button-group.scss","../../scss/_nav.scss","../../scss/_navbar.scss","../../scss/_card.scss","../../scss/_accordion.scss","../../scss/_breadcrumb.scss","../../scss/_pagination.scss","../../scss/mixins/_pagination.scss","../../scss/_badge.scss","../../scss/_alert.scss","../../scss/mixins/_alert.scss","../../scss/_progress.scss","../../scss/_list-group.scss","../../scss/mixins/_list-group.scss","../../scss/_close.scss","../../scss/_toasts.scss","../../scss/_modal.scss","../../scss/mixins/_backdrop.scss","../../scss/_tooltip.scss","../../scss/mixins/_reset-text.scss","../../scss/_popover.scss","../../scss/_carousel.scss","../../scss/mixins/_clearfix.scss","../../scss/_spinners.scss","../../scss/_offcanvas.scss","../../scss/_placeholders.scss","../../scss/helpers/_color-bg.scss","../../scss/helpers/_colored-links.scss","../../scss/helpers/_ratio.scss","../../scss/helpers/_position.scss","../../scss/helpers/_stacks.scss","../../scss/helpers/_visually-hidden.scss","../../scss/mixins/_visually-hidden.scss","../../scss/helpers/_stretched-link.scss","../../scss/helpers/_text-truncation.scss","../../scss/mixins/_text-truncate.scss","../../scss/helpers/_vr.scss","../../scss/mixins/_utilities.scss","../../scss/utilities/_api.scss"],"names":[],"mappings":"iBACE;;;;;ACDF,MAQI,UAAA,QAAA,YAAA,QAAA,YAAA,QAAA,UAAA,QAAA,SAAA,QAAA,YAAA,QAAA,YAAA,QAAA,WAAA,QAAA,UAAA,QAAA,UAAA,QAAA,WAAA,KAAA,WAAA,KAAA,UAAA,QAAA,eAAA,QAIA,cAAA,QAAA,cAAA,QAAA,cAAA,QAAA,cAAA,QAAA,cAAA,QAAA,cAAA,QAAA,cAAA,QAAA,cAAA,QAAA,cAAA,QAIA,aAAA,QAAA,eAAA,QAAA,aAAA,QAAA,UAAA,QAAA,aAAA,QAAA,YAAA,QAAA,WAAA,QAAA,UAAA,QAIA,iBAAA,EAAA,CAAA,GAAA,CAAA,IAAA,mBAAA,GAAA,CAAA,GAAA,CAAA,IAAA,iBAAA,EAAA,CAAA,GAAA,CAAA,GAAA,cAAA,EAAA,CAAA,GAAA,CAAA,IAAA,iBAAA,GAAA,CAAA,GAAA,CAAA,EAAA,gBAAA,GAAA,CAAA,EAAA,CAAA,GAAA,eAAA,GAAA,CAAA,GAAA,CAAA,IAAA,cAAA,EAAA,CAAA,EAAA,CAAA,GAGF,eAAA,GAAA,CAAA,GAAA,CAAA,IACA,eAAA,CAAA,CAAA,CAAA,CAAA,EACA,oBAAA,EAAA,CAAA,EAAA,CAAA,GACA,iBAAA,GAAA,CAAA,GAAA,CAAA,IAMA,qBAAA,SAAA,CAAA,aAAA,CAAA,UAAA,CAAA,MAAA,CAAA,gBAAA,CAAA,WAAA,CAAA,iBAAA,CAAA,KAAA,CAAA,UAAA,CAAA,mBAAA,CAAA,gBAAA,CAAA,iBAAA,CAAA,mBACA,oBAAA,cAAA,CAAA,KAAA,CAAA,MAAA,CAAA,QAAA,CAAA,iBAAA,CAAA,aAAA,CAAA,UACA,cAAA,2EAOA,sBAAA,0BC4PI,oBAAA,KD1PJ,sBAAA,IACA,sBAAA,IACA,gBAAA,QAIA,aAAA,KAIA,kBAAA,IACA,kBAAA,MACA,kBAAA,QACA,8BAAA,qBAEA,mBAAA,SACA,sBAAA,QACA,sBAAA,OACA,sBAAA,KACA,uBAAA,KACA,wBAAA,MAGA,gBAAA,QACA,sBAAA,QAEA,gBAAA,QAEA,kBAAA,QExDF,EC+DA,QADA,SD3DE,WAAA,WAeE,8CANJ,MAOM,gBAAA,QAcN,KACE,OAAA,EACA,YAAA,2BDmPI,UAAA,yBCjPJ,YAAA,2BACA,YAAA,2BACA,MAAA,qBACA,WAAA,0BACA,iBAAA,kBACA,yBAAA,KACA,4BAAA,YASF,GACE,OAAA,KAAA,EACA,MAAA,QACA,OAAA,EACA,WAAA,IAAA,MACA,QAAA,IAUF,IAAA,IAAA,IAAA,IAAA,IAAA,IAAA,GAAA,GAAA,GAAA,GAAA,GAAA,GACE,WAAA,EACA,cAAA,MAGA,YAAA,IACA,YAAA,IAIF,IAAA,GD6MQ,UAAA,uBAlKJ,0BC3CJ,IAAA,GDoNQ,UAAA,QC/MR,IAAA,GDwMQ,UAAA,sBAlKJ,0BCtCJ,IAAA,GD+MQ,UAAA,MC1MR,IAAA,GDmMQ,UAAA,oBAlKJ,0BCjCJ,IAAA,GD0MQ,UAAA,SCrMR,IAAA,GD8LQ,UAAA,sBAlKJ,0BC5BJ,IAAA,GDqMQ,UAAA,QChMR,IAAA,GDqLM,UAAA,QChLN,IAAA,GDgLM,UAAA,KCrKN,EACE,WAAA,EACA,cAAA,KAUF,YACE,wBAAA,UAAA,OAAA,gBAAA,UAAA,OACA,OAAA,KACA,iCAAA,KAAA,yBAAA,KAMF,QACE,cAAA,KACA,WAAA,OACA,YAAA,QAMF,GCsBA,GDpBE,aAAA,KC0BF,GDvBA,GCsBA,GDnBE,WAAA,EACA,cAAA,KAGF,MCuBA,MACA,MAFA,MDlBE,cAAA,EAGF,GACE,YAAA,IAKF,GACE,cAAA,MACA,YAAA,EAMF,WACE,OAAA,EAAA,EAAA,KAQF,ECYA,ODVE,YAAA,OAQF,OAAA,MDmFM,UAAA,OC5EN,MAAA,KACE,QAAA,QACA,iBAAA,uBASF,ICFA,IDIE,SAAA,SD+DI,UAAA,MC7DJ,YAAA,EACA,eAAA,SAGF,IAAM,OAAA,OACN,IAAM,IAAA,MAKN,EACE,MAAA,qBACA,gBAAA,UAEA,QACE,MAAA,2BAWF,2BAAA,iCAEE,MAAA,QACA,gBAAA,KCNJ,KACA,IDYA,ICXA,KDeE,YAAA,yBDqBI,UAAA,ICbN,IACE,QAAA,MACA,WAAA,EACA,cAAA,KACA,SAAA,KDSI,UAAA,OCJJ,SDII,UAAA,QCFF,MAAA,QACA,WAAA,OAIJ,KDHM,UAAA,OCKJ,MAAA,qBACA,UAAA,WAGA,OACE,MAAA,QAIJ,IACE,QAAA,SAAA,QDfI,UAAA,OCiBJ,MAAA,kBACA,iBAAA,qBEpSE,cAAA,OFuSF,QACE,QAAA,EDtBE,UAAA,ICiCN,OACE,OAAA,EAAA,EAAA,KAMF,IChCA,IDkCE,eAAA,OAQF,MACE,aAAA,OACA,gBAAA,SAGF,QACE,YAAA,MACA,eAAA,MACA,MAAA,QACA,WAAA,KAOF,GAEE,WAAA,QACA,WAAA,qBCvCF,MAGA,GAFA,MAGA,GDsCA,MCxCA,GD8CE,aAAA,QACA,aAAA,MACA,aAAA,EAQF,MACE,QAAA,aAMF,OAEE,cAAA,EAQF,iCACE,QAAA,ECrDF,OD0DA,MCxDA,SADA,OAEA,SD4DE,OAAA,EACA,YAAA,QDrHI,UAAA,QCuHJ,YAAA,QAIF,OC3DA,OD6DE,eAAA,KAKF,cACE,OAAA,QAGF,OAGE,UAAA,OAGA,gBACE,QAAA,EAOJ,0IACE,QAAA,eCjEF,cACA,aACA,cDuEA,OAIE,mBAAA,OCvEF,6BACA,4BACA,6BDwEI,sBACE,OAAA,QAON,mBACE,QAAA,EACA,aAAA,KAKF,SACE,OAAA,SAUF,SACE,UAAA,EACA,QAAA,EACA,OAAA,EACA,OAAA,EAQF,OACE,MAAA,KACA,MAAA,KACA,QAAA,EACA,cAAA,MD1MM,UAAA,sBC6MN,YAAA,QD/WE,0BCwWJ,OD/LQ,UAAA,QCwMN,SACE,MAAA,KC/EJ,kCDsFA,uCCvFA,mCADA,+BAGA,oCAJA,6BAKA,mCD2FE,QAAA,EAGF,4BACE,OAAA,KASF,cACE,eAAA,KACA,mBAAA,UAmBF,4BACE,mBAAA,KAKF,+BACE,QAAA,EAOF,6BACE,KAAA,QACA,mBAAA,OAFF,uBACE,KAAA,QACA,mBAAA,OAKF,OACE,QAAA,aAKF,OACE,OAAA,EAOF,QACE,QAAA,UACA,OAAA,QAQF,SACE,eAAA,SAQF,SACE,QAAA,eGpkBF,MJyQM,UAAA,QIvQJ,YAAA,IAKA,WJsQM,UAAA,uBIlQJ,YAAA,IACA,YAAA,IJ+FA,0BIpGF,WJ6QM,UAAA,MI7QN,WJsQM,UAAA,uBIlQJ,YAAA,IACA,YAAA,IJ+FA,0BIpGF,WJ6QM,UAAA,QI7QN,WJsQM,UAAA,uBIlQJ,YAAA,IACA,YAAA,IJ+FA,0BIpGF,WJ6QM,UAAA,MI7QN,WJsQM,UAAA,uBIlQJ,YAAA,IACA,YAAA,IJ+FA,0BIpGF,WJ6QM,UAAA,QI7QN,WJsQM,UAAA,uBIlQJ,YAAA,IACA,YAAA,IJ+FA,0BIpGF,WJ6QM,UAAA,MI7QN,WJsQM,UAAA,uBIlQJ,YAAA,IACA,YAAA,IJ+FA,0BIpGF,WJ6QM,UAAA,QIrPR,eCvDE,aAAA,EACA,WAAA,KD2DF,aC5DE,aAAA,EACA,WAAA,KD8DF,kBACE,QAAA,aAEA,mCACE,aAAA,MAUJ,YJoNM,UAAA,OIlNJ,eAAA,UAIF,YACE,cAAA,KJ6MI,UAAA,QI1MJ,wBACE,cAAA,EAIJ,mBACE,WAAA,MACA,cAAA,KJmMI,UAAA,OIjMJ,MAAA,QAEA,2BACE,QAAA,KEhGJ,WCIE,UAAA,KAGA,OAAA,KDDF,eACE,QAAA,OACA,iBAAA,KACA,OAAA,IAAA,MAAA,uBHGE,cAAA,QIRF,UAAA,KAGA,OAAA,KDcF,QAEE,QAAA,aAGF,YACE,cAAA,MACA,YAAA,EAGF,gBN+PM,UAAA,OM7PJ,MAAA,QElCA,WN8mBF,iBAGA,cACA,cACA,cAHA,cADA,eOlnBE,cAAA,OACA,cAAA,EACA,MAAA,KACA,cAAA,8BACA,aAAA,8BACA,aAAA,KACA,YAAA,KCsDE,yBF5CE,WAAA,cACE,UAAA,OE2CJ,yBF5CE,WAAA,cAAA,cACE,UAAA,OE2CJ,yBF5CE,WAAA,cAAA,cAAA,cACE,UAAA,OE2CJ,0BF5CE,WAAA,cAAA,cAAA,cAAA,cACE,UAAA,QE2CJ,0BF5CE,WAAA,cAAA,cAAA,cAAA,cAAA,eACE,UAAA,QGfN,KCAA,cAAA,OACA,cAAA,EACA,QAAA,KACA,UAAA,KAEA,WAAA,8BACA,aAAA,+BACA,YAAA,+BDJE,OCaF,YAAA,EACA,MAAA,KACA,UAAA,KACA,cAAA,8BACA,aAAA,8BACA,WAAA,mBA+CI,KACE,KAAA,EAAA,EAAA,GAGF,iBApCJ,KAAA,EAAA,EAAA,KACA,MAAA,KAcA,cACE,KAAA,EAAA,EAAA,KACA,MAAA,KAFF,cACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,cACE,KAAA,EAAA,EAAA,KACA,MAAA,eAFF,cACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,cACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,cACE,KAAA,EAAA,EAAA,KACA,MAAA,eA+BE,UAhDJ,KAAA,EAAA,EAAA,KACA,MAAA,KAqDQ,OAhEN,KAAA,EAAA,EAAA,KACA,MAAA,YA+DM,OAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,OAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,OAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,OAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,OAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,OAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,OAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,OAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,QAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,QAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,QAhEN,KAAA,EAAA,EAAA,KACA,MAAA,KAuEQ,UAxDV,YAAA,YAwDU,UAxDV,YAAA,aAwDU,UAxDV,YAAA,IAwDU,UAxDV,YAAA,aAwDU,UAxDV,YAAA,aAwDU,UAxDV,YAAA,IAwDU,UAxDV,YAAA,aAwDU,UAxDV,YAAA,aAwDU,UAxDV,YAAA,IAwDU,WAxDV,YAAA,aAwDU,WAxDV,YAAA,aAmEM,KVitBR,MU/sBU,cAAA,EAGF,KVitBR,MU/sBU,cAAA,EAPF,KV2tBR,MUztBU,cAAA,QAGF,KV2tBR,MUztBU,cAAA,QAPF,KVquBR,MUnuBU,cAAA,OAGF,KVquBR,MUnuBU,cAAA,OAPF,KV+uBR,MU7uBU,cAAA,KAGF,KV+uBR,MU7uBU,cAAA,KAPF,KVyvBR,MUvvBU,cAAA,OAGF,KVyvBR,MUvvBU,cAAA,OAPF,KVmwBR,MUjwBU,cAAA,KAGF,KVmwBR,MUjwBU,cAAA,KF1DN,yBEUE,QACE,KAAA,EAAA,EAAA,GAGF,oBApCJ,KAAA,EAAA,EAAA,KACA,MAAA,KAcA,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,KAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,eAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,eA+BE,aAhDJ,KAAA,EAAA,EAAA,KACA,MAAA,KAqDQ,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,YA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,KAuEQ,aAxDV,YAAA,EAwDU,aAxDV,YAAA,YAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,IAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,IAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,IAwDU,cAxDV,YAAA,aAwDU,cAxDV,YAAA,aAmEM,QVq4BR,SUn4BU,cAAA,EAGF,QVo4BR,SUl4BU,cAAA,EAPF,QV64BR,SU34BU,cAAA,QAGF,QV44BR,SU14BU,cAAA,QAPF,QVq5BR,SUn5BU,cAAA,OAGF,QVo5BR,SUl5BU,cAAA,OAPF,QV65BR,SU35BU,cAAA,KAGF,QV45BR,SU15BU,cAAA,KAPF,QVq6BR,SUn6BU,cAAA,OAGF,QVo6BR,SUl6BU,cAAA,OAPF,QV66BR,SU36BU,cAAA,KAGF,QV46BR,SU16BU,cAAA,MF1DN,yBEUE,QACE,KAAA,EAAA,EAAA,GAGF,oBApCJ,KAAA,EAAA,EAAA,KACA,MAAA,KAcA,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,KAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,eAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,eA+BE,aAhDJ,KAAA,EAAA,EAAA,KACA,MAAA,KAqDQ,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,YA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,KAuEQ,aAxDV,YAAA,EAwDU,aAxDV,YAAA,YAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,IAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,IAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,IAwDU,cAxDV,YAAA,aAwDU,cAxDV,YAAA,aAmEM,QV8iCR,SU5iCU,cAAA,EAGF,QV6iCR,SU3iCU,cAAA,EAPF,QVsjCR,SUpjCU,cAAA,QAGF,QVqjCR,SUnjCU,cAAA,QAPF,QV8jCR,SU5jCU,cAAA,OAGF,QV6jCR,SU3jCU,cAAA,OAPF,QVskCR,SUpkCU,cAAA,KAGF,QVqkCR,SUnkCU,cAAA,KAPF,QV8kCR,SU5kCU,cAAA,OAGF,QV6kCR,SU3kCU,cAAA,OAPF,QVslCR,SUplCU,cAAA,KAGF,QVqlCR,SUnlCU,cAAA,MF1DN,yBEUE,QACE,KAAA,EAAA,EAAA,GAGF,oBApCJ,KAAA,EAAA,EAAA,KACA,MAAA,KAcA,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,KAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,eAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,eA+BE,aAhDJ,KAAA,EAAA,EAAA,KACA,MAAA,KAqDQ,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,YA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,KAuEQ,aAxDV,YAAA,EAwDU,aAxDV,YAAA,YAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,IAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,IAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,IAwDU,cAxDV,YAAA,aAwDU,cAxDV,YAAA,aAmEM,QVutCR,SUrtCU,cAAA,EAGF,QVstCR,SUptCU,cAAA,EAPF,QV+tCR,SU7tCU,cAAA,QAGF,QV8tCR,SU5tCU,cAAA,QAPF,QVuuCR,SUruCU,cAAA,OAGF,QVsuCR,SUpuCU,cAAA,OAPF,QV+uCR,SU7uCU,cAAA,KAGF,QV8uCR,SU5uCU,cAAA,KAPF,QVuvCR,SUrvCU,cAAA,OAGF,QVsvCR,SUpvCU,cAAA,OAPF,QV+vCR,SU7vCU,cAAA,KAGF,QV8vCR,SU5vCU,cAAA,MF1DN,0BEUE,QACE,KAAA,EAAA,EAAA,GAGF,oBApCJ,KAAA,EAAA,EAAA,KACA,MAAA,KAcA,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,KAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,eAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,iBACE,KAAA,EAAA,EAAA,KACA,MAAA,eA+BE,aAhDJ,KAAA,EAAA,EAAA,KACA,MAAA,KAqDQ,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,YA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,UAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,KAuEQ,aAxDV,YAAA,EAwDU,aAxDV,YAAA,YAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,IAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,IAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,aAwDU,aAxDV,YAAA,IAwDU,cAxDV,YAAA,aAwDU,cAxDV,YAAA,aAmEM,QVg4CR,SU93CU,cAAA,EAGF,QV+3CR,SU73CU,cAAA,EAPF,QVw4CR,SUt4CU,cAAA,QAGF,QVu4CR,SUr4CU,cAAA,QAPF,QVg5CR,SU94CU,cAAA,OAGF,QV+4CR,SU74CU,cAAA,OAPF,QVw5CR,SUt5CU,cAAA,KAGF,QVu5CR,SUr5CU,cAAA,KAPF,QVg6CR,SU95CU,cAAA,OAGF,QV+5CR,SU75CU,cAAA,OAPF,QVw6CR,SUt6CU,cAAA,KAGF,QVu6CR,SUr6CU,cAAA,MF1DN,0BEUE,SACE,KAAA,EAAA,EAAA,GAGF,qBApCJ,KAAA,EAAA,EAAA,KACA,MAAA,KAcA,kBACE,KAAA,EAAA,EAAA,KACA,MAAA,KAFF,kBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,kBACE,KAAA,EAAA,EAAA,KACA,MAAA,eAFF,kBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,kBACE,KAAA,EAAA,EAAA,KACA,MAAA,IAFF,kBACE,KAAA,EAAA,EAAA,KACA,MAAA,eA+BE,cAhDJ,KAAA,EAAA,EAAA,KACA,MAAA,KAqDQ,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,YA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,WAhEN,KAAA,EAAA,EAAA,KACA,MAAA,IA+DM,YAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,YAhEN,KAAA,EAAA,EAAA,KACA,MAAA,aA+DM,YAhEN,KAAA,EAAA,EAAA,KACA,MAAA,KAuEQ,cAxDV,YAAA,EAwDU,cAxDV,YAAA,YAwDU,cAxDV,YAAA,aAwDU,cAxDV,YAAA,IAwDU,cAxDV,YAAA,aAwDU,cAxDV,YAAA,aAwDU,cAxDV,YAAA,IAwDU,cAxDV,YAAA,aAwDU,cAxDV,YAAA,aAwDU,cAxDV,YAAA,IAwDU,eAxDV,YAAA,aAwDU,eAxDV,YAAA,aAmEM,SVyiDR,UUviDU,cAAA,EAGF,SVwiDR,UUtiDU,cAAA,EAPF,SVijDR,UU/iDU,cAAA,QAGF,SVgjDR,UU9iDU,cAAA,QAPF,SVyjDR,UUvjDU,cAAA,OAGF,SVwjDR,UUtjDU,cAAA,OAPF,SVikDR,UU/jDU,cAAA,KAGF,SVgkDR,UU9jDU,cAAA,KAPF,SVykDR,UUvkDU,cAAA,OAGF,SVwkDR,UUtkDU,cAAA,OAPF,SVilDR,UU/kDU,cAAA,KAGF,SVglDR,UU9kDU,cAAA,MCrHV,OACE,iBAAA,qBACA,cAAA,YACA,wBAAA,uBACA,qBAAA,YACA,yBAAA,qBACA,sBAAA,oBACA,wBAAA,qBACA,qBAAA,mBACA,uBAAA,qBACA,oBAAA,qBAEA,MAAA,KACA,cAAA,KACA,MAAA,sBACA,eAAA,IACA,aAAA,6BAOA,yBACE,QAAA,MAAA,MACA,iBAAA,mBACA,oBAAA,IACA,WAAA,MAAA,EAAA,EAAA,EAAA,OAAA,0BAGF,aACE,eAAA,QAGF,aACE,eAAA,OAIJ,qBACE,WAAA,IAAA,MAAA,aAOF,aACE,aAAA,IAUA,4BACE,QAAA,OAAA,OAeF,gCACE,aAAA,IAAA,EAGA,kCACE,aAAA,EAAA,IAOJ,oCACE,oBAAA,EAGF,qCACE,iBAAA,EAUF,2CACE,qBAAA,2BACA,MAAA,8BAMF,uDACE,qBAAA,2BACA,MAAA,8BAQJ,cACE,qBAAA,0BACA,MAAA,6BAQA,8BACE,qBAAA,yBACA,MAAA,4BCrIF,eAOE,iBAAA,KACA,cAAA,QACA,wBAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,sBACA,aAAA,6BAlBF,iBAOE,iBAAA,KACA,cAAA,QACA,wBAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,sBACA,aAAA,6BAlBF,eAOE,iBAAA,KACA,cAAA,QACA,wBAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,sBACA,aAAA,6BAlBF,YAOE,iBAAA,KACA,cAAA,QACA,wBAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,sBACA,aAAA,6BAlBF,eAOE,iBAAA,KACA,cAAA,QACA,wBAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,sBACA,aAAA,6BAlBF,cAOE,iBAAA,KACA,cAAA,QACA,wBAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,sBACA,aAAA,6BAlBF,aAOE,iBAAA,KACA,cAAA,QACA,wBAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,sBACA,aAAA,6BAlBF,YAOE,iBAAA,KACA,cAAA,QACA,wBAAA,QACA,sBAAA,QACA,yBAAA,KACA,qBAAA,QACA,wBAAA,KACA,oBAAA,QACA,uBAAA,KAEA,MAAA,sBACA,aAAA,6BD0IA,kBACE,WAAA,KACA,2BAAA,MHpFF,4BGkFA,qBACE,WAAA,KACA,2BAAA,OHpFF,4BGkFA,qBACE,WAAA,KACA,2BAAA,OHpFF,4BGkFA,qBACE,WAAA,KACA,2BAAA,OHpFF,6BGkFA,qBACE,WAAA,KACA,2BAAA,OHpFF,6BGkFA,sBACE,WAAA,KACA,2BAAA,OE5JN,YACE,cAAA,MASF,gBACE,YAAA,oBACA,eAAA,oBACA,cAAA,EfoRI,UAAA,QehRJ,YAAA,IAIF,mBACE,YAAA,kBACA,eAAA,kBf0QI,UAAA,QetQN,mBACE,YAAA,mBACA,eAAA,mBfoQI,UAAA,QgBjSN,WACE,WAAA,OhBgSI,UAAA,OgB5RJ,MAAA,QCLF,cACE,QAAA,MACA,MAAA,KACA,QAAA,QAAA,OjB8RI,UAAA,KiB3RJ,YAAA,IACA,YAAA,IACA,MAAA,QACA,iBAAA,KACA,gBAAA,YACA,OAAA,IAAA,MAAA,QACA,mBAAA,KAAA,gBAAA,KAAA,WAAA,KdGE,cAAA,QeHE,WAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAIA,uCDhBN,cCiBQ,WAAA,MDGN,yBACE,SAAA,OAEA,wDACE,OAAA,QAKJ,oBACE,MAAA,QACA,iBAAA,KACA,aAAA,QACA,QAAA,EAKE,WAAA,EAAA,EAAA,EAAA,OAAA,qBAOJ,2CAEE,OAAA,MAIF,gCACE,MAAA,QAEA,QAAA,EAHF,2BACE,MAAA,QAEA,QAAA,EAQF,uBAEE,iBAAA,QAGA,QAAA,EAIF,0CACE,QAAA,QAAA,OACA,OAAA,SAAA,QACA,mBAAA,OAAA,kBAAA,OACA,MAAA,QE3EF,iBAAA,QF6EE,eAAA,KACA,aAAA,QACA,aAAA,MACA,aAAA,EACA,wBAAA,IACA,cAAA,ECtEE,mBAAA,MAAA,KAAA,WAAA,CAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAAA,WAAA,MAAA,KAAA,WAAA,CAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YD2DJ,oCACE,QAAA,QAAA,OACA,OAAA,SAAA,QACA,mBAAA,OAAA,kBAAA,OACA,MAAA,QE3EF,iBAAA,QF6EE,eAAA,KACA,aAAA,QACA,aAAA,MACA,aAAA,EACA,wBAAA,IACA,cAAA,ECtEE,WAAA,MAAA,KAAA,WAAA,CAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAIA,uCDuDJ,0CCtDM,mBAAA,KAAA,WAAA,KDsDN,oCCtDM,WAAA,MDqEN,+EACE,iBAAA,QADF,yEACE,iBAAA,QASJ,wBACE,QAAA,MACA,MAAA,KACA,QAAA,QAAA,EACA,cAAA,EACA,YAAA,IACA,MAAA,QACA,iBAAA,YACA,OAAA,MAAA,YACA,aAAA,IAAA,EAEA,8BACE,QAAA,EAGF,wCAAA,wCAEE,cAAA,EACA,aAAA,EAWJ,iBACE,WAAA,0BACA,QAAA,OAAA,MjBkKI,UAAA,QGlRF,cAAA,OcoHF,6CACE,QAAA,OAAA,MACA,OAAA,QAAA,OACA,mBAAA,MAAA,kBAAA,MAHF,uCACE,QAAA,OAAA,MACA,OAAA,QAAA,OACA,mBAAA,MAAA,kBAAA,MAIJ,iBACE,WAAA,yBACA,QAAA,MAAA,KjBqJI,UAAA,QGlRF,cAAA,MciIF,6CACE,QAAA,MAAA,KACA,OAAA,OAAA,MACA,mBAAA,KAAA,kBAAA,KAHF,uCACE,QAAA,MAAA,KACA,OAAA,OAAA,MACA,mBAAA,KAAA,kBAAA,KAQF,sBACE,WAAA,2BAGF,yBACE,WAAA,0BAGF,yBACE,WAAA,yBAKJ,oBACE,MAAA,KACA,OAAA,2BACA,QAAA,QAEA,mDACE,OAAA,QAGF,uCACE,OAAA,YdpKA,cAAA,QcwKF,0CdxKE,cAAA,Qc4KF,oCAAoB,OAAA,0BACpB,oCAAoB,OAAA,yBG3LtB,aACE,QAAA,MACA,MAAA,KACA,QAAA,QAAA,QAAA,QAAA,OACA,mBAAA,oBpB4RI,UAAA,KoBzRJ,YAAA,IACA,YAAA,IACA,MAAA,QACA,iBAAA,KACA,iBAAA,gOACA,kBAAA,UACA,oBAAA,MAAA,OAAA,OACA,gBAAA,KAAA,KACA,OAAA,IAAA,MAAA,QjBDE,cAAA,QeHE,WAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YEQJ,mBAAA,KAAA,gBAAA,KAAA,WAAA,KFJI,uCEfN,aFgBQ,WAAA,MEKN,mBACE,aAAA,QACA,QAAA,EAKE,WAAA,EAAA,EAAA,EAAA,OAAA,qBAIJ,uBAAA,mCAEE,cAAA,OACA,iBAAA,KAGF,sBAEE,iBAAA,QAKF,4BACE,MAAA,YACA,YAAA,EAAA,EAAA,EAAA,QAIJ,gBACE,YAAA,OACA,eAAA,OACA,aAAA,MpB0OI,UAAA,QGlRF,cAAA,OiB6CJ,gBACE,YAAA,MACA,eAAA,MACA,aAAA,KpBkOI,UAAA,QGlRF,cAAA,MkBfJ,YACE,QAAA,MACA,WAAA,OACA,aAAA,MACA,cAAA,QAEA,8BACE,MAAA,KACA,YAAA,OAIJ,oBACE,cAAA,MACA,aAAA,EACA,WAAA,MAEA,sCACE,MAAA,MACA,aAAA,OACA,YAAA,EAIJ,kBACE,MAAA,IACA,OAAA,IACA,WAAA,MACA,eAAA,IACA,iBAAA,KACA,kBAAA,UACA,oBAAA,OACA,gBAAA,QACA,OAAA,IAAA,MAAA,gBACA,mBAAA,KAAA,gBAAA,KAAA,WAAA,KACA,2BAAA,MAAA,aAAA,MAAA,mBAAA,MAGA,iClBvBE,cAAA,MkB2BF,8BAEE,cAAA,IAGF,yBACE,OAAA,gBAGF,wBACE,aAAA,QACA,QAAA,EACA,WAAA,EAAA,EAAA,EAAA,OAAA,qBAGF,0BACE,iBAAA,QACA,aAAA,QAEA,yCAII,iBAAA,8NAIJ,sCAII,iBAAA,sIAKN,+CACE,iBAAA,QACA,aAAA,QAKE,iBAAA,wNAIJ,2BACE,eAAA,KACA,OAAA,KACA,QAAA,GAOA,6CAAA,8CACE,OAAA,QACA,QAAA,GAcN,aACE,aAAA,MAEA,+BACE,MAAA,IACA,YAAA,OACA,iBAAA,uJACA,oBAAA,KAAA,OlB3GA,cAAA,IeHE,WAAA,oBAAA,KAAA,YAIA,uCGsGJ,+BHrGM,WAAA,MG6GJ,qCACE,iBAAA,yIAGF,uCACE,oBAAA,MAAA,OAKE,iBAAA,sIAKN,gCACE,cAAA,MACA,aAAA,EAEA,kDACE,aAAA,OACA,YAAA,EAKN,mBACE,QAAA,aACA,aAAA,KAGF,WACE,SAAA,SACA,KAAA,cACA,eAAA,KAIE,yBAAA,0BACE,eAAA,KACA,OAAA,KACA,QAAA,ICrKN,YACE,MAAA,KACA,OAAA,OACA,QAAA,EACA,iBAAA,YACA,mBAAA,KAAA,gBAAA,KAAA,WAAA,KAEA,kBACE,QAAA,EAIA,wCAA0B,WAAA,EAAA,EAAA,EAAA,IAAA,IAAA,CAAA,EAAA,EAAA,EAAA,OAAA,qBAC1B,oCAA0B,WAAA,EAAA,EAAA,EAAA,IAAA,IAAA,CAAA,EAAA,EAAA,EAAA,OAAA,qBAG5B,8BACE,OAAA,EAGF,kCACE,MAAA,KACA,OAAA,KACA,WAAA,QHzBF,iBAAA,QG2BE,OAAA,EnBZA,cAAA,KeHE,mBAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAAA,WAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YImBF,mBAAA,KAAA,WAAA,KJfE,uCIMJ,kCJLM,mBAAA,KAAA,WAAA,MIgBJ,yCHjCF,iBAAA,QGsCA,2CACE,MAAA,KACA,OAAA,MACA,MAAA,YACA,OAAA,QACA,iBAAA,QACA,aAAA,YnB7BA,cAAA,KmBkCF,8BACE,MAAA,KACA,OAAA,KHnDF,iBAAA,QGqDE,OAAA,EnBtCA,cAAA,KeHE,gBAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAAA,WAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YI6CF,gBAAA,KAAA,WAAA,KJzCE,uCIiCJ,8BJhCM,gBAAA,KAAA,WAAA,MI0CJ,qCH3DF,iBAAA,QGgEA,8BACE,MAAA,KACA,OAAA,MACA,MAAA,YACA,OAAA,QACA,iBAAA,QACA,aAAA,YnBvDA,cAAA,KmB4DF,qBACE,eAAA,KAEA,2CACE,iBAAA,QAGF,uCACE,iBAAA,QCvFN,eACE,SAAA,SAEA,6BrBs5EF,uCACA,4BqBp5EI,OAAA,mBACA,YAAA,KAGF,qBACE,SAAA,SACA,IAAA,EACA,KAAA,EACA,MAAA,KACA,OAAA,KACA,QAAA,KAAA,OACA,SAAA,OACA,WAAA,MACA,cAAA,SACA,YAAA,OACA,eAAA,KACA,OAAA,IAAA,MAAA,YACA,iBAAA,EAAA,ELPE,WAAA,QAAA,IAAA,WAAA,CAAA,UAAA,IAAA,YAIA,uCKVJ,qBLWM,WAAA,MKMN,6BrBy5EF,uCqBv5EI,QAAA,KAAA,OAEA,yDAAA,+CACE,MAAA,YrB25EN,oDqB55EI,0CACE,MAAA,YAGF,oEAAA,0DAEE,YAAA,SACA,eAAA,QrB65EN,6CACA,+DqBj6EI,mCAAA,qDAEE,YAAA,SACA,eAAA,QrBm6EN,wDqBh6EI,8CACE,YAAA,SACA,eAAA,QAIJ,4BACE,YAAA,SACA,eAAA,QAOA,gEACE,QAAA,IACA,UAAA,WAAA,mBAAA,mBrB65EN,6CqB/5EI,yCrB85EJ,2DAEA,kCqB/5EM,QAAA,IACA,UAAA,WAAA,mBAAA,mBAKF,oDACE,QAAA,IACA,UAAA,WAAA,mBAAA,mBAKF,6CACE,aAAA,IAAA,ECnEN,aACE,SAAA,SACA,QAAA,KACA,UAAA,KACA,YAAA,QACA,MAAA,KAEA,2BtBk+EF,4BADA,0BsB99EI,SAAA,SACA,KAAA,EAAA,EAAA,KACA,MAAA,GACA,UAAA,EAIF,iCtBg+EF,yCADA,gCsB59EI,QAAA,EAMF,kBACE,SAAA,SACA,QAAA,EAEA,wBACE,QAAA,EAWN,kBACE,QAAA,KACA,YAAA,OACA,QAAA,QAAA,OxBoPI,UAAA,KwBlPJ,YAAA,IACA,YAAA,IACA,MAAA,QACA,WAAA,OACA,YAAA,OACA,iBAAA,QACA,OAAA,IAAA,MAAA,QrBtCE,cAAA,QD+/EJ,qBsB/8EA,8BtB68EA,6BACA,kCsB18EE,QAAA,MAAA,KxB8NI,UAAA,QGlRF,cAAA,MDwgFJ,qBsB/8EA,8BtB68EA,6BACA,kCsB18EE,QAAA,OAAA,MxBqNI,UAAA,QGlRF,cAAA,OqBkEJ,6BtB68EA,6BsB38EE,cAAA,KtBg9EF,uEACA,gFACA,+EsBr8EI,kHrBjEA,wBAAA,EACA,2BAAA,ED0gFJ,iEACA,6EACA,4EsBn8EI,+GrB1EA,wBAAA,EACA,2BAAA,EqBsFF,0IACE,YAAA,KrB1EA,uBAAA,EACA,0BAAA,EqB6EF,4DtB27EF,2DCzgFI,uBAAA,EACA,0BAAA,EsBzBF,gBACE,QAAA,KACA,MAAA,KACA,WAAA,OzByQE,UAAA,OyBtQF,MAAA,QAGF,eACE,SAAA,SACA,IAAA,KACA,QAAA,EACA,QAAA,KACA,UAAA,KACA,QAAA,OAAA,MACA,WAAA,MzB4PE,UAAA,QyBzPF,MAAA,KACA,iBAAA,mBtB1BA,cAAA,QDokFJ,0BACA,yBuBtiFI,sCvBoiFJ,qCuBliFM,QAAA,MA9CF,uBAAA,mCAoDE,aAAA,QAGE,cAAA,qBACA,iBAAA,0OACA,kBAAA,UACA,oBAAA,MAAA,wBAAA,OACA,gBAAA,sBAAA,sBAGF,6BAAA,yCACE,aAAA,QACA,WAAA,EAAA,EAAA,EAAA,OAAA,oBAhEJ,2CAAA,+BAyEI,cAAA,qBACA,oBAAA,IAAA,wBAAA,MAAA,wBA1EJ,sBAAA,kCAiFE,aAAA,QAGE,kDAAA,gDAAA,8DAAA,4DAEE,cAAA,SACA,iBAAA,+NAAA,CAAA,0OACA,oBAAA,MAAA,OAAA,MAAA,CAAA,OAAA,MAAA,QACA,gBAAA,KAAA,IAAA,CAAA,sBAAA,sBAIJ,4BAAA,wCACE,aAAA,QACA,WAAA,EAAA,EAAA,EAAA,OAAA,oBA/FJ,6BAAA,yCAuGI,MAAA,kCAvGJ,2BAAA,uCA8GE,aAAA,QAEA,mCAAA,+CACE,iBAAA,QAGF,iCAAA,6CACE,WAAA,EAAA,EAAA,EAAA,OAAA,oBAGF,6CAAA,yDACE,MAAA,QAKJ,qDACE,YAAA,KA/HF,gDvB+oFJ,wDAFA,+CuB7oFI,4DvB8oFJ,oEAFA,2DuBngFU,QAAA,EAtHR,kBACE,QAAA,KACA,MAAA,KACA,WAAA,OzByQE,UAAA,OyBtQF,MAAA,QAGF,iBACE,SAAA,SACA,IAAA,KACA,QAAA,EACA,QAAA,KACA,UAAA,KACA,QAAA,OAAA,MACA,WAAA,MzB4PE,UAAA,QyBzPF,MAAA,KACA,iBAAA,mBtB1BA,cAAA,QD8pFJ,8BACA,6BuBhoFI,0CvB8nFJ,yCuB5nFM,QAAA,MA9CF,yBAAA,qCAoDE,aAAA,QAGE,cAAA,qBACA,iBAAA,2TACA,kBAAA,UACA,oBAAA,MAAA,wBAAA,OACA,gBAAA,sBAAA,sBAGF,+BAAA,2CACE,aAAA,QACA,WAAA,EAAA,EAAA,EAAA,OAAA,oBAhEJ,6CAAA,iCAyEI,cAAA,qBACA,oBAAA,IAAA,wBAAA,MAAA,wBA1EJ,wBAAA,oCAiFE,aAAA,QAGE,oDAAA,kDAAA,gEAAA,8DAEE,cAAA,SACA,iBAAA,+NAAA,CAAA,2TACA,oBAAA,MAAA,OAAA,MAAA,CAAA,OAAA,MAAA,QACA,gBAAA,KAAA,IAAA,CAAA,sBAAA,sBAIJ,8BAAA,0CACE,aAAA,QACA,WAAA,EAAA,EAAA,EAAA,OAAA,oBA/FJ,+BAAA,2CAuGI,MAAA,kCAvGJ,6BAAA,yCA8GE,aAAA,QAEA,qCAAA,iDACE,iBAAA,QAGF,mCAAA,+CACE,WAAA,EAAA,EAAA,EAAA,OAAA,oBAGF,+CAAA,2DACE,MAAA,QAKJ,uDACE,YAAA,KA/HF,kDvByuFJ,0DAFA,iDuBvuFI,8DvBwuFJ,sEAFA,6DuB3lFU,QAAA,EC7IV,KAEE,mBAAA,QACA,mBAAA,SACA,qBAAA,E1B6RI,mBAAA,K0B3RJ,qBAAA,IACA,qBAAA,IACA,eAAA,QACA,YAAA,YACA,sBAAA,IACA,sBAAA,YACA,uBAAA,SACA,4BAAA,YACA,oBAAA,MAAA,EAAA,IAAA,EAAA,yBAAA,CAAA,EAAA,IAAA,IAAA,qBACA,0BAAA,KACA,0BAAA,EAAA,EAAA,EAAA,QAAA,yCAGA,QAAA,aACA,QAAA,wBAAA,wBACA,YAAA,0B1B4QI,UAAA,wB0B1QJ,YAAA,0BACA,YAAA,0BACA,MAAA,oBACA,WAAA,OACA,gBAAA,KAEA,eAAA,OACA,OAAA,QACA,oBAAA,KAAA,iBAAA,KAAA,YAAA,KACA,OAAA,2BAAA,MAAA,2BvBjBE,cAAA,4BgBfF,iBAAA,iBDYI,WAAA,MAAA,KAAA,WAAA,CAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAIA,uCQhBN,KRiBQ,WAAA,MQqBN,WACE,MAAA,0BAEA,iBAAA,uBACA,aAAA,iCAGF,sBAEE,MAAA,oBACA,iBAAA,iBACA,aAAA,2BAGF,mBACE,MAAA,0BPrDF,iBAAA,uBOuDE,aAAA,iCACA,QAAA,EAKE,WAAA,+BAIJ,8BACE,aAAA,iCACA,QAAA,EAKE,WAAA,+BAIJ,wBAAA,YAAA,UAAA,wBAAA,6BAKE,MAAA,2BACA,iBAAA,wBAGA,aAAA,kCAGA,sCAAA,0BAAA,wBAAA,sCAAA,2CAKI,WAAA,+BAKN,cAAA,cAAA,uBAGE,MAAA,6BACA,eAAA,KACA,iBAAA,0BAEA,aAAA,oCACA,QAAA,+BAYF,aCtGA,eAAA,KACA,YAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,EAAA,CAAA,GAAA,CAAA,IACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,KACA,qBAAA,QACA,+BAAA,QDyFA,eCtGA,eAAA,KACA,YAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,GAAA,CAAA,GAAA,CAAA,IACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,KACA,qBAAA,QACA,+BAAA,QDyFA,aCtGA,eAAA,KACA,YAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,EAAA,CAAA,GAAA,CAAA,IACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,KACA,qBAAA,QACA,+BAAA,QDyFA,UCtGA,eAAA,KACA,YAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,EAAA,CAAA,GAAA,CAAA,IACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,KACA,qBAAA,QACA,+BAAA,QDyFA,aCtGA,eAAA,KACA,YAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,GAAA,CAAA,GAAA,CAAA,EACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,KACA,qBAAA,QACA,+BAAA,QDyFA,YCtGA,eAAA,KACA,YAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,GAAA,CAAA,EAAA,CAAA,GACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,KACA,qBAAA,QACA,+BAAA,QDyFA,WCtGA,eAAA,KACA,YAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,GAAA,CAAA,GAAA,CAAA,IACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,KACA,qBAAA,QACA,+BAAA,QDyFA,UCtGA,eAAA,KACA,YAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,EAAA,CAAA,EAAA,CAAA,GACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,KACA,qBAAA,QACA,+BAAA,QDmHA,qBCvGA,eAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,EAAA,CAAA,GAAA,CAAA,IACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,QACA,qBAAA,YACA,+BAAA,QACA,cAAA,KD0FA,uBCvGA,eAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,GAAA,CAAA,GAAA,CAAA,IACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,QACA,qBAAA,YACA,+BAAA,QACA,cAAA,KD0FA,qBCvGA,eAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,EAAA,CAAA,GAAA,CAAA,GACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,QACA,qBAAA,YACA,+BAAA,QACA,cAAA,KD0FA,kBCvGA,eAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,EAAA,CAAA,GAAA,CAAA,IACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,QACA,qBAAA,YACA,+BAAA,QACA,cAAA,KD0FA,qBCvGA,eAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,GAAA,CAAA,GAAA,CAAA,EACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,QACA,qBAAA,YACA,+BAAA,QACA,cAAA,KD0FA,oBCvGA,eAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,GAAA,CAAA,EAAA,CAAA,GACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,QACA,qBAAA,YACA,+BAAA,QACA,cAAA,KD0FA,mBCvGA,eAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,GAAA,CAAA,GAAA,CAAA,IACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,QACA,qBAAA,YACA,+BAAA,QACA,cAAA,KD0FA,kBCvGA,eAAA,QACA,sBAAA,QACA,qBAAA,KACA,kBAAA,QACA,4BAAA,QACA,0BAAA,EAAA,CAAA,EAAA,CAAA,GACA,sBAAA,KACA,mBAAA,QACA,6BAAA,QACA,uBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,QACA,qBAAA,YACA,+BAAA,QACA,cAAA,KDsGF,UACE,qBAAA,IACA,eAAA,qBACA,YAAA,YACA,sBAAA,YACA,qBAAA,2BACA,4BAAA,YACA,sBAAA,2BACA,6BAAA,YACA,wBAAA,QACA,+BAAA,YACA,oBAAA,KACA,0BAAA,EAAA,CAAA,GAAA,CAAA,IAEA,gBAAA,UAUA,wBACE,MAAA,oBAGF,gBACE,MAAA,0BAWJ,mBAAA,QCxIE,mBAAA,OACA,mBAAA,K3BoOI,mBAAA,Q2BlOJ,uBAAA,ODyIF,mBAAA,QC5IE,mBAAA,QACA,mBAAA,O3BoOI,mBAAA,S2BlOJ,uBAAA,QCnEF,MVgBM,WAAA,QAAA,KAAA,OAIA,uCUpBN,MVqBQ,WAAA,MUlBN,iBACE,QAAA,EAMF,qBACE,QAAA,KAIJ,YACE,OAAA,EACA,SAAA,OVDI,WAAA,OAAA,KAAA,KAIA,uCULN,YVMQ,WAAA,MUDN,gCACE,MAAA,EACA,OAAA,KVNE,WAAA,MAAA,KAAA,KAIA,uCUAJ,gCVCM,WAAA,MhBuoGR,UAGA,iBAJA,SAEA,W2B5pGA,Q3B6pGA,e2BvpGE,SAAA,SAGF,iBACE,YAAA,OCmBE,wBACE,QAAA,aACA,YAAA,OACA,eAAA,OACA,QAAA,GAhCJ,WAAA,KAAA,MACA,aAAA,KAAA,MAAA,YACA,cAAA,EACA,YAAA,KAAA,MAAA,YAqDE,8BACE,YAAA,EDzCN,eAEE,qBAAA,KACA,wBAAA,MACA,wBAAA,EACA,wBAAA,OACA,qBAAA,S7B6QI,wBAAA,K6B3QJ,oBAAA,QACA,iBAAA,KACA,2BAAA,mCACA,4BAAA,SACA,2BAAA,IACA,kCAAA,qBACA,yBAAA,mCACA,+BAAA,OACA,yBAAA,EAAA,OAAA,KAAA,oBACA,yBAAA,QACA,+BAAA,QACA,4BAAA,QACA,gCAAA,KACA,6BAAA,QACA,kCAAA,QACA,6BAAA,KACA,6BAAA,QACA,2BAAA,QACA,+BAAA,KACA,+BAAA,OAGA,SAAA,SACA,QAAA,0BACA,QAAA,KACA,UAAA,6BACA,QAAA,6BAAA,6BACA,OAAA,E7BgPI,UAAA,6B6B9OJ,MAAA,yBACA,WAAA,KACA,WAAA,KACA,iBAAA,sBACA,gBAAA,YACA,OAAA,gCAAA,MAAA,gC1BzCE,cAAA,iC0B6CF,+BACE,IAAA,KACA,KAAA,EACA,WAAA,0BAwBA,qBACE,cAAA,MAEA,qCACE,MAAA,KACA,KAAA,EAIJ,mBACE,cAAA,IAEA,mCACE,MAAA,EACA,KAAA,KnB1CJ,yBmB4BA,wBACE,cAAA,MAEA,wCACE,MAAA,KACA,KAAA,EAIJ,sBACE,cAAA,IAEA,sCACE,MAAA,EACA,KAAA,MnB1CJ,yBmB4BA,wBACE,cAAA,MAEA,wCACE,MAAA,KACA,KAAA,EAIJ,sBACE,cAAA,IAEA,sCACE,MAAA,EACA,KAAA,MnB1CJ,yBmB4BA,wBACE,cAAA,MAEA,wCACE,MAAA,KACA,KAAA,EAIJ,sBACE,cAAA,IAEA,sCACE,MAAA,EACA,KAAA,MnB1CJ,0BmB4BA,wBACE,cAAA,MAEA,wCACE,MAAA,KACA,KAAA,EAIJ,sBACE,cAAA,IAEA,sCACE,MAAA,EACA,KAAA,MnB1CJ,0BmB4BA,yBACE,cAAA,MAEA,yCACE,MAAA,KACA,KAAA,EAIJ,uBACE,cAAA,IAEA,uCACE,MAAA,EACA,KAAA,MAUN,uCACE,IAAA,KACA,OAAA,KACA,WAAA,EACA,cAAA,0BCzFA,gCACE,QAAA,aACA,YAAA,OACA,eAAA,OACA,QAAA,GAzBJ,WAAA,EACA,aAAA,KAAA,MAAA,YACA,cAAA,KAAA,MACA,YAAA,KAAA,MAAA,YA8CE,sCACE,YAAA,EDqEJ,wCACE,IAAA,EACA,MAAA,KACA,KAAA,KACA,WAAA,EACA,YAAA,0BCvGA,iCACE,QAAA,aACA,YAAA,OACA,eAAA,OACA,QAAA,GAlBJ,WAAA,KAAA,MAAA,YACA,aAAA,EACA,cAAA,KAAA,MAAA,YACA,YAAA,KAAA,MAuCE,uCACE,YAAA,ED+EF,iCACE,eAAA,EAMJ,0CACE,IAAA,EACA,MAAA,KACA,KAAA,KACA,WAAA,EACA,aAAA,0BCxHA,mCACE,QAAA,aACA,YAAA,OACA,eAAA,OACA,QAAA,GAWA,mCACE,QAAA,KAGF,oCACE,QAAA,aACA,aAAA,OACA,eAAA,OACA,QAAA,GA9BN,WAAA,KAAA,MAAA,YACA,aAAA,KAAA,MACA,cAAA,KAAA,MAAA,YAiCE,yCACE,YAAA,EDgGF,oCACE,eAAA,EAON,kBACE,OAAA,EACA,OAAA,oCAAA,EACA,SAAA,OACA,WAAA,IAAA,MAAA,8BACA,QAAA,EAMF,eACE,QAAA,MACA,MAAA,KACA,QAAA,kCAAA,kCACA,MAAA,KACA,YAAA,IACA,MAAA,8BACA,WAAA,QACA,gBAAA,KACA,YAAA,OACA,iBAAA,YACA,OAAA,EAEA,qBAAA,qBAEE,MAAA,oCVzLF,iBAAA,iCU8LA,sBAAA,sBAEE,MAAA,qCACA,gBAAA,KVjMF,iBAAA,kCUqMA,wBAAA,wBAEE,MAAA,uCACA,eAAA,KACA,iBAAA,YAMJ,oBACE,QAAA,MAIF,iBACE,QAAA,MACA,QAAA,oCAAA,oCACA,cAAA,E7B0EI,UAAA,Q6BxEJ,MAAA,gCACA,YAAA,OAIF,oBACE,QAAA,MACA,QAAA,kCAAA,kCACA,MAAA,8BAIF,oBAEE,oBAAA,QACA,iBAAA,QACA,2BAAA,mCACA,yBAAA,EACA,yBAAA,QACA,+BAAA,KACA,yBAAA,mCACA,4BAAA,0BACA,gCAAA,KACA,6BAAA,QACA,kCAAA,QACA,2BAAA,QErPF,W7Bs9GA,oB6Bp9GE,SAAA,SACA,QAAA,YACA,eAAA,O7Bw9GF,yB6Bt9GE,gBACE,SAAA,SACA,KAAA,EAAA,EAAA,K7B89GJ,4CACA,0CAIA,gCADA,gCADA,+BADA,+B6B39GE,mC7Bo9GF,iCAIA,uBADA,uBADA,sBADA,sB6B/8GI,QAAA,EAKJ,aACE,QAAA,KACA,UAAA,KACA,gBAAA,WAEA,0BACE,MAAA,KAIJ,W5BhBI,cAAA,QD0+GJ,wC6Bt9GE,6CAEE,YAAA,K7By9GJ,4CADA,kD6Bp9GE,uD5BVE,wBAAA,EACA,2BAAA,EDo+GJ,6C6Bj9GE,+B7Bg9GF,iCCt9GI,uBAAA,EACA,0BAAA,E4BwBJ,uBACE,cAAA,SACA,aAAA,SAEA,8BAAA,uCAAA,sCAGE,YAAA,EAGF,0CACE,aAAA,EAIJ,0CAAA,+BACE,cAAA,QACA,aAAA,QAGF,0CAAA,+BACE,cAAA,OACA,aAAA,OAoBF,oBACE,eAAA,OACA,YAAA,WACA,gBAAA,OAEA,yB7B+6GF,+B6B76GI,MAAA,K7Bi7GJ,iD6B96GE,2CAEE,WAAA,K7Bg7GJ,qD6B56GE,gE5B1FE,2BAAA,EACA,0BAAA,ED0gHJ,sD6B56GE,8B5B7GE,uBAAA,EACA,wBAAA,E6BxBJ,KAEE,wBAAA,KACA,wBAAA,OAEA,0BAAA,EACA,oBAAA,qBACA,0BAAA,2BACA,6BAAA,QAGA,QAAA,KACA,UAAA,KACA,aAAA,EACA,cAAA,EACA,WAAA,KAGF,UACE,QAAA,MACA,QAAA,6BAAA,6BhC4QI,UAAA,6BgC1QJ,YAAA,+BACA,MAAA,yBACA,gBAAA,KdbI,WAAA,MAAA,KAAA,WAAA,CAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,YAIA,uCcGN,UdFQ,WAAA,McWN,gBAAA,gBAEE,MAAA,+BAKF,mBACE,MAAA,kCACA,eAAA,KACA,OAAA,QAQJ,UAEE,2BAAA,IACA,2BAAA,QACA,4BAAA,SACA,sCAAA,QAAA,QAAA,QACA,gCAAA,QACA,6BAAA,KACA,uCAAA,QAAA,QAAA,KAGA,cAAA,gCAAA,MAAA,gCAEA,oBACE,cAAA,2CACA,WAAA,IACA,OAAA,gCAAA,MAAA,Y7BtCA,uBAAA,iCACA,wBAAA,iC6BwCA,0BAAA,0BAGE,UAAA,QACA,aAAA,2CAGF,6BAAA,6BAEE,MAAA,kCACA,iBAAA,YACA,aAAA,Y9B0iHN,mC8BtiHE,2BAEE,MAAA,qCACA,iBAAA,kCACA,aAAA,4CAGF,yBAEE,WAAA,2C7BjEA,uBAAA,EACA,wBAAA,E6B2EJ,WAEE,6BAAA,SACA,iCAAA,KACA,8BAAA,QAGA,qBACE,WAAA,IACA,OAAA,E7B9FA,cAAA,kC6BiGA,8BACE,MAAA,kCACA,iBAAA,YACA,aAAA,YAIJ,4B9B0hHF,2B8BxhHI,MAAA,sCbzHF,iBAAA,mCjBupHF,oB8BnhHE,oBAEE,KAAA,EAAA,EAAA,KACA,WAAA,O9BshHJ,yB8BjhHE,yBAEE,WAAA,EACA,UAAA,EACA,WAAA,OAMF,8B9B8gHF,mC8B7gHI,MAAA,KAUF,uBACE,QAAA,KAEF,qBACE,QAAA,MCpKJ,QAEE,sBAAA,EACA,sBAAA,OACA,kBAAA,oBACA,wBAAA,mBACA,2BAAA,mBACA,yBAAA,mBACA,4BAAA,UACA,6BAAA,KACA,4BAAA,QACA,wBAAA,mBACA,8BAAA,mBACA,+BAAA,OACA,8BAAA,QACA,8BAAA,QACA,8BAAA,QACA,4BAAA,4OACA,iCAAA,mBACA,kCAAA,SACA,gCAAA,QACA,+BAAA,WAAA,MAAA,YAGA,SAAA,SACA,QAAA,KACA,UAAA,KACA,YAAA,OACA,gBAAA,cACA,QAAA,2BAAA,2BAMA,mB/BwqHF,yBAGA,sBADA,sBADA,sBAGA,sBACA,uB+B5qHI,QAAA,KACA,UAAA,QACA,YAAA,OACA,gBAAA,cAoBJ,cACE,YAAA,iCACA,eAAA,iCACA,aAAA,kCjCkOI,UAAA,iCiChOJ,MAAA,6BACA,gBAAA,KACA,YAAA,OAEA,oBAAA,oBAEE,MAAA,mCAUJ,YAEE,wBAAA,EACA,wBAAA,OAEA,0BAAA,EACA,oBAAA,uBACA,0BAAA,6BACA,6BAAA,gCAGA,QAAA,KACA,eAAA,OACA,aAAA,EACA,cAAA,EACA,WAAA,K/BkpHF,6B+BhpHE,4BAEE,MAAA,8BAGF,2BACE,SAAA,OASJ,aACE,YAAA,MACA,eAAA,MACA,MAAA,uBAEA,e/B0oHF,qBADA,qB+BtoHI,MAAA,8BAaJ,iBACE,WAAA,KACA,UAAA,EAGA,YAAA,OAIF,gBACE,QAAA,mCAAA,mCjCiJI,UAAA,mCiC/IJ,YAAA,EACA,MAAA,uBACA,iBAAA,YACA,OAAA,uBAAA,MAAA,sC9BtIE,cAAA,uCeHE,WAAA,oCAIA,uCe+HN,gBf9HQ,WAAA,MewIN,sBACE,gBAAA,KAGF,sBACE,gBAAA,KACA,QAAA,EACA,WAAA,EAAA,EAAA,EAAA,qCAMJ,qBACE,QAAA,aACA,MAAA,MACA,OAAA,MACA,eAAA,OACA,iBAAA,iCACA,kBAAA,UACA,oBAAA,OACA,gBAAA,KAGF,mBACE,WAAA,6BACA,WAAA,KvBxHE,yBuBoIA,kBAEI,UAAA,OACA,gBAAA,WAEA,8BACE,eAAA,IAEA,6CACE,SAAA,SAGF,wCACE,cAAA,oCACA,aAAA,oCAIJ,qCACE,SAAA,QAGF,mCACE,QAAA,eACA,WAAA,KAGF,kCACE,QAAA,KAGF,6BAEE,SAAA,OACA,QAAA,KACA,UAAA,EACA,MAAA,eACA,OAAA,eACA,WAAA,kBACA,iBAAA,sBACA,OAAA,YACA,UAAA,ef5NJ,WAAA,KeiOI,+CACE,QAAA,KAGF,6CACE,QAAA,KACA,UAAA,EACA,QAAA,EACA,WAAA,SvB1LR,yBuBoIA,kBAEI,UAAA,OACA,gBAAA,WAEA,8BACE,eAAA,IAEA,6CACE,SAAA,SAGF,wCACE,cAAA,oCACA,aAAA,oCAIJ,qCACE,SAAA,QAGF,mCACE,QAAA,eACA,WAAA,KAGF,kCACE,QAAA,KAGF,6BAEE,SAAA,OACA,QAAA,KACA,UAAA,EACA,MAAA,eACA,OAAA,eACA,WAAA,kBACA,iBAAA,sBACA,OAAA,YACA,UAAA,ef5NJ,WAAA,KeiOI,+CACE,QAAA,KAGF,6CACE,QAAA,KACA,UAAA,EACA,QAAA,EACA,WAAA,SvB1LR,yBuBoIA,kBAEI,UAAA,OACA,gBAAA,WAEA,8BACE,eAAA,IAEA,6CACE,SAAA,SAGF,wCACE,cAAA,oCACA,aAAA,oCAIJ,qCACE,SAAA,QAGF,mCACE,QAAA,eACA,WAAA,KAGF,kCACE,QAAA,KAGF,6BAEE,SAAA,OACA,QAAA,KACA,UAAA,EACA,MAAA,eACA,OAAA,eACA,WAAA,kBACA,iBAAA,sBACA,OAAA,YACA,UAAA,ef5NJ,WAAA,KeiOI,+CACE,QAAA,KAGF,6CACE,QAAA,KACA,UAAA,EACA,QAAA,EACA,WAAA,SvB1LR,0BuBoIA,kBAEI,UAAA,OACA,gBAAA,WAEA,8BACE,eAAA,IAEA,6CACE,SAAA,SAGF,wCACE,cAAA,oCACA,aAAA,oCAIJ,qCACE,SAAA,QAGF,mCACE,QAAA,eACA,WAAA,KAGF,kCACE,QAAA,KAGF,6BAEE,SAAA,OACA,QAAA,KACA,UAAA,EACA,MAAA,eACA,OAAA,eACA,WAAA,kBACA,iBAAA,sBACA,OAAA,YACA,UAAA,ef5NJ,WAAA,KeiOI,+CACE,QAAA,KAGF,6CACE,QAAA,KACA,UAAA,EACA,QAAA,EACA,WAAA,SvB1LR,0BuBoIA,mBAEI,UAAA,OACA,gBAAA,WAEA,+BACE,eAAA,IAEA,8CACE,SAAA,SAGF,yCACE,cAAA,oCACA,aAAA,oCAIJ,sCACE,SAAA,QAGF,oCACE,QAAA,eACA,WAAA,KAGF,mCACE,QAAA,KAGF,8BAEE,SAAA,OACA,QAAA,KACA,UAAA,EACA,MAAA,eACA,OAAA,eACA,WAAA,kBACA,iBAAA,sBACA,OAAA,YACA,UAAA,ef5NJ,WAAA,KeiOI,gDACE,QAAA,KAGF,8CACE,QAAA,KACA,UAAA,EACA,QAAA,EACA,WAAA,SAtDR,eAEI,UAAA,OACA,gBAAA,WAEA,2BACE,eAAA,IAEA,0CACE,SAAA,SAGF,qCACE,cAAA,oCACA,aAAA,oCAIJ,kCACE,SAAA,QAGF,gCACE,QAAA,eACA,WAAA,KAGF,+BACE,QAAA,KAGF,0BAEE,SAAA,OACA,QAAA,KACA,UAAA,EACA,MAAA,eACA,OAAA,eACA,WAAA,kBACA,iBAAA,sBACA,OAAA,YACA,UAAA,ef5NJ,WAAA,KeiOI,4CACE,QAAA,KAGF,0CACE,QAAA,KACA,UAAA,EACA,QAAA,EACA,WAAA,QAiBZ,aAEE,kBAAA,0BACA,wBAAA,0BACA,2BAAA,0BACA,yBAAA,KACA,wBAAA,KACA,8BAAA,KACA,iCAAA,yBACA,4BAAA,kPC/QF,MAEE,mBAAA,KACA,mBAAA,KACA,yBAAA,OACA,uBAAA,IACA,uBAAA,mCACA,wBAAA,SACA,qBAAA,EACA,8BAAA,qBACA,wBAAA,OACA,wBAAA,KACA,iBAAA,oBACA,oBAAA,EACA,iBAAA,EACA,gBAAA,EACA,aAAA,KACA,8BAAA,KACA,uBAAA,QAGA,SAAA,SACA,QAAA,KACA,eAAA,OACA,UAAA,EACA,OAAA,sBACA,UAAA,WACA,iBAAA,kBACA,gBAAA,WACA,OAAA,4BAAA,MAAA,4B/BdE,cAAA,6B+BkBF,SACE,aAAA,EACA,YAAA,EAGF,kBACE,WAAA,QACA,cAAA,QAEA,8BACE,iBAAA,E/BnBF,uBAAA,mCACA,wBAAA,mC+BsBA,6BACE,oBAAA,E/BVF,2BAAA,mCACA,0BAAA,mC+BgBF,+BhC+kIF,+BgC7kII,WAAA,EAIJ,WAGE,KAAA,EAAA,EAAA,KACA,QAAA,wBAAA,wBACA,MAAA,qBAGF,YACE,cAAA,8BAGF,eACE,WAAA,0CACA,cAAA,EAGF,sBACE,cAAA,EAQA,sBACE,YAAA,wBAQJ,aACE,QAAA,6BAAA,6BACA,cAAA,EACA,MAAA,yBACA,iBAAA,sBACA,cAAA,4BAAA,MAAA,4BAEA,yB/BxFE,cAAA,mCAAA,mCAAA,EAAA,E+B6FJ,aACE,QAAA,6BAAA,6BACA,MAAA,yBACA,iBAAA,sBACA,WAAA,4BAAA,MAAA,4BAEA,wB/BnGE,cAAA,EAAA,EAAA,mCAAA,mC+B6GJ,kBACE,aAAA,yCACA,cAAA,wCACA,YAAA,yCACA,cAAA,EAEA,mCACE,iBAAA,kBACA,oBAAA,kBAIJ,mBACE,aAAA,yCACA,YAAA,yCAIF,kBACE,SAAA,SACA,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,mC/BrIE,cAAA,mC+ByIJ,UhC0jIA,iBADA,cgCtjIE,MAAA,KAGF,UhCyjIA,cC/rII,uBAAA,mCACA,wBAAA,mC+B0IJ,UhC0jIA,iBCvrII,2BAAA,mCACA,0BAAA,mC+ByIF,kBACE,cAAA,4BxBtHA,yBwBkHJ,YAQI,QAAA,KACA,UAAA,IAAA,KAGA,kBAEE,KAAA,EAAA,EAAA,GACA,cAAA,EAEA,wBACE,YAAA,EACA,YAAA,EAKA,mC/BtKJ,wBAAA,EACA,2BAAA,EDutIJ,gDgC/iIU,iDAGE,wBAAA,EhCgjIZ,gDgC9iIU,oDAGE,2BAAA,EAIJ,oC/BvKJ,uBAAA,EACA,0BAAA,EDqtIJ,iDgC5iIU,kDAGE,uBAAA,EhC6iIZ,iDgC3iIU,qDAGE,0BAAA,GC/NZ,WAEE,qBAAA,QACA,kBAAA,KACA,0BAAA,MAAA,MAAA,WAAA,CAAA,iBAAA,MAAA,WAAA,CAAA,aAAA,MAAA,WAAA,CAAA,WAAA,MAAA,WAAA,CAAA,cAAA,MAAA,KACA,4BAAA,uBACA,4BAAA,IACA,6BAAA,SACA,mCAAA,qBACA,6BAAA,QACA,6BAAA,KACA,yBAAA,QACA,sBAAA,uBACA,wBAAA,gRACA,8BAAA,QACA,kCAAA,gBACA,mCAAA,UAAA,KAAA,YACA,+BAAA,gRACA,sCAAA,QACA,oCAAA,EAAA,EAAA,EAAA,QAAA,yBACA,8BAAA,QACA,8BAAA,KACA,4BAAA,QACA,yBAAA,QAIF,kBACE,SAAA,SACA,QAAA,KACA,YAAA,OACA,MAAA,KACA,QAAA,kCAAA,kCnCiQI,UAAA,KmC/PJ,MAAA,8BACA,WAAA,KACA,iBAAA,2BACA,OAAA,EhCtBE,cAAA,EgCwBF,gBAAA,KjB3BI,WAAA,+BAIA,uCiBWN,kBjBVQ,WAAA,MiByBN,kCACE,MAAA,iCACA,iBAAA,8BACA,WAAA,MAAA,EAAA,4CAAA,EAAA,iCAEA,yCACE,iBAAA,oCACA,UAAA,uCAKJ,yBACE,YAAA,EACA,MAAA,mCACA,OAAA,mCACA,YAAA,KACA,QAAA,GACA,iBAAA,6BACA,kBAAA,UACA,gBAAA,mCjBlDE,WAAA,wCAIA,uCiBsCJ,yBjBrCM,WAAA,MiBiDN,wBACE,QAAA,EAGF,wBACE,QAAA,EACA,aAAA,2CACA,QAAA,EACA,WAAA,yCAIJ,kBACE,cAAA,EAGF,gBACE,MAAA,0BACA,iBAAA,uBACA,OAAA,iCAAA,MAAA,iCAEA,8BhC/DE,uBAAA,kCACA,wBAAA,kCgCiEA,gDhClEA,uBAAA,wCACA,wBAAA,wCgCsEF,oCACE,WAAA,EAIF,6BhC9DE,2BAAA,kCACA,0BAAA,kCgCiEE,yDhClEF,2BAAA,wCACA,0BAAA,wCgCsEA,iDhCvEA,2BAAA,kCACA,0BAAA,kCgC4EJ,gBACE,QAAA,mCAAA,mCASA,qCACE,aAAA,EAGF,iCACE,aAAA,EACA,YAAA,EhCpHA,cAAA,EgCuHA,6CAAgB,WAAA,EAChB,4CAAe,cAAA,EAGb,mDAAA,6DhC3HF,cAAA,EiCnBJ,YAEE,0BAAA,EACA,0BAAA,EACA,8BAAA,KAEA,mBAAA,EACA,8BAAA,EACA,8BAAA,QACA,+BAAA,OACA,kCAAA,QAGA,QAAA,KACA,UAAA,KACA,QAAA,+BAAA,+BACA,cAAA,mCpCqRI,UAAA,+BoCnRJ,WAAA,KACA,iBAAA,wBjCAE,cAAA,mCiCMF,kCACE,aAAA,oCAEA,0CACE,MAAA,KACA,cAAA,oCACA,MAAA,mCACA,QAAA,kCAIJ,wBACE,MAAA,uCCrCJ,YAEE,0BAAA,QACA,0BAAA,SrCkSI,0BAAA,KqChSJ,sBAAA,qBACA,mBAAA,KACA,6BAAA,IACA,6BAAA,QACA,8BAAA,SACA,4BAAA,2BACA,yBAAA,QACA,mCAAA,QACA,4BAAA,2BACA,yBAAA,QACA,iCAAA,EAAA,EAAA,EAAA,QAAA,yBACA,6BAAA,KACA,0BAAA,QACA,oCAAA,QACA,+BAAA,QACA,4BAAA,KACA,sCAAA,QAGA,QAAA,KhCpBA,aAAA,EACA,WAAA,KgCuBF,WACE,SAAA,SACA,QAAA,MACA,QAAA,+BAAA,+BrCsQI,UAAA,+BqCpQJ,MAAA,2BACA,gBAAA,KACA,iBAAA,wBACA,OAAA,kCAAA,MAAA,kCnBpBI,WAAA,MAAA,KAAA,WAAA,CAAA,iBAAA,KAAA,WAAA,CAAA,aAAA,KAAA,WAAA,CAAA,WAAA,KAAA,YAIA,uCmBQN,WnBPQ,WAAA,MmBkBN,iBACE,QAAA,EACA,MAAA,iCAEA,iBAAA,8BACA,aAAA,wCAGF,iBACE,QAAA,EACA,MAAA,iCACA,iBAAA,8BACA,QAAA,EACA,WAAA,sCAGF,mBAAA,kBAEE,QAAA,EACA,MAAA,kClBtDF,iBAAA,+BkBwDE,aAAA,yCAGF,qBAAA,oBAEE,MAAA,oCACA,eAAA,KACA,iBAAA,iCACA,aAAA,2CAKF,wCACE,YAAA,KAKE,kClC9BF,uBAAA,mCACA,0BAAA,mCkCmCE,iClClDF,wBAAA,mCACA,2BAAA,mCkCkEJ,eClGE,0BAAA,OACA,0BAAA,QtCgSI,0BAAA,QsC9RJ,8BAAA,ODmGF,eCtGE,0BAAA,OACA,0BAAA,QtCgSI,0BAAA,SsC9RJ,8BAAA,QCFF,OAEE,qBAAA,OACA,qBAAA,OvC6RI,qBAAA,OuC3RJ,uBAAA,IACA,iBAAA,KACA,yBAAA,SAGA,QAAA,aACA,QAAA,0BAAA,0BvCqRI,UAAA,0BuCnRJ,YAAA,4BACA,YAAA,EACA,MAAA,sBACA,WAAA,OACA,YAAA,OACA,eAAA,SpCJE,cAAA,8BoCSF,aACE,QAAA,KAKJ,YACE,SAAA,SACA,IAAA,KChCF,OAEE,cAAA,YACA,qBAAA,KACA,qBAAA,KACA,yBAAA,KACA,iBAAA,QACA,wBAAA,YACA,kBAAA,IAAA,MAAA,6BACA,yBAAA,SAGA,SAAA,SACA,QAAA,0BAAA,0BACA,cAAA,8BACA,MAAA,sBACA,iBAAA,mBACA,OAAA,uBrCFE,cAAA,8BqCOJ,eAEE,MAAA,QAIF,YACE,YAAA,IAQF,mBACE,cAAA,KAGA,8BACE,SAAA,SACA,IAAA,EACA,MAAA,EACA,QAAA,EACA,QAAA,QAAA,KAgBF,eChEA,iBAAA,QACA,cAAA,QACA,wBAAA,QAMA,2BACE,MAAA,QDuDF,iBChEA,iBAAA,QACA,cAAA,QACA,wBAAA,QAMA,6BACE,MAAA,QDuDF,eChEA,iBAAA,QACA,cAAA,QACA,wBAAA,QAMA,2BACE,MAAA,QDuDF,YChEA,iBAAA,QACA,cAAA,QACA,wBAAA,QAMA,wBACE,MAAA,QDuDF,eChEA,iBAAA,QACA,cAAA,QACA,wBAAA,QAMA,2BACE,MAAA,QDuDF,cChEA,iBAAA,QACA,cAAA,QACA,wBAAA,QAMA,0BACE,MAAA,QDuDF,aChEA,iBAAA,QACA,cAAA,QACA,wBAAA,QAMA,yBACE,MAAA,QDuDF,YChEA,iBAAA,QACA,cAAA,QACA,wBAAA,QAMA,wBACE,MAAA,QCPF,gCACE,GAAK,sBAAA,MAKT,UAEE,qBAAA,K1CyRI,wBAAA,Q0CvRJ,iBAAA,QACA,4BAAA,SACA,yBAAA,MAAA,EAAA,IAAA,IAAA,qBACA,wBAAA,KACA,qBAAA,QACA,6BAAA,MAAA,KAAA,KAGA,QAAA,KACA,OAAA,0BACA,SAAA,O1C6QI,UAAA,6B0C3QJ,iBAAA,sBvCPE,cAAA,iCuCYJ,cACE,QAAA,KACA,eAAA,OACA,gBAAA,OACA,SAAA,OACA,MAAA,6BACA,WAAA,OACA,YAAA,OACA,iBAAA,0BxBvBI,WAAA,kCAIA,uCwBWN,cxBVQ,WAAA,MwBsBR,sBvBCE,iBAAA,iKuBCA,gBAAA,0BAAA,0BAIA,uBACE,UAAA,GAAA,OAAA,SAAA,qBAGE,uCAJJ,uBAKM,UAAA,MClDR,YAEE,sBAAA,QACA,mBAAA,KACA,6BAAA,qBACA,6BAAA,IACA,8BAAA,SACA,+BAAA,KACA,+BAAA,OACA,6BAAA,QACA,mCAAA,QACA,gCAAA,QACA,oCAAA,QACA,iCAAA,QACA,+BAAA,QACA,4BAAA,KACA,6BAAA,KACA,0BAAA,QACA,oCAAA,QAGA,QAAA,KACA,eAAA,OAGA,aAAA,EACA,cAAA,ExCXE,cAAA,mCwCeJ,qBACE,gBAAA,KACA,cAAA,QAEA,8CAEE,QAAA,uBAAA,KACA,kBAAA,QASJ,wBACE,MAAA,KACA,MAAA,kCACA,WAAA,QAGA,8BAAA,8BAEE,QAAA,EACA,MAAA,wCACA,gBAAA,KACA,iBAAA,qCAGF,+BACE,MAAA,yCACA,iBAAA,sCAQJ,iBACE,SAAA,SACA,QAAA,MACA,QAAA,oCAAA,oCACA,MAAA,2BACA,gBAAA,KACA,iBAAA,wBACA,OAAA,kCAAA,MAAA,kCAEA,6BxCvDE,uBAAA,QACA,wBAAA,QwC0DF,4BxC7CE,2BAAA,QACA,0BAAA,QwCgDF,0BAAA,0BAEE,MAAA,oCACA,eAAA,KACA,iBAAA,iCAIF,wBACE,QAAA,EACA,MAAA,kCACA,iBAAA,+BACA,aAAA,yCAIF,kCACE,iBAAA,EAEA,yCACE,WAAA,6CACA,iBAAA,kCAaF,uBACE,eAAA,IAGE,qExCvDJ,0BAAA,mCAZA,wBAAA,EwCwEI,qExCxEJ,wBAAA,mCAYA,0BAAA,EwCiEI,+CACE,WAAA,EAGF,yDACE,iBAAA,kCACA,kBAAA,EAEA,gEACE,YAAA,6CACA,kBAAA,kCjCtFR,yBiC8DA,0BACE,eAAA,IAGE,wExCvDJ,0BAAA,mCAZA,wBAAA,EwCwEI,wExCxEJ,wBAAA,mCAYA,0BAAA,EwCiEI,kDACE,WAAA,EAGF,4DACE,iBAAA,kCACA,kBAAA,EAEA,mEACE,YAAA,6CACA,kBAAA,mCjCtFR,yBiC8DA,0BACE,eAAA,IAGE,wExCvDJ,0BAAA,mCAZA,wBAAA,EwCwEI,wExCxEJ,wBAAA,mCAYA,0BAAA,EwCiEI,kDACE,WAAA,EAGF,4DACE,iBAAA,kCACA,kBAAA,EAEA,mEACE,YAAA,6CACA,kBAAA,mCjCtFR,yBiC8DA,0BACE,eAAA,IAGE,wExCvDJ,0BAAA,mCAZA,wBAAA,EwCwEI,wExCxEJ,wBAAA,mCAYA,0BAAA,EwCiEI,kDACE,WAAA,EAGF,4DACE,iBAAA,kCACA,kBAAA,EAEA,mEACE,YAAA,6CACA,kBAAA,mCjCtFR,0BiC8DA,0BACE,eAAA,IAGE,wExCvDJ,0BAAA,mCAZA,wBAAA,EwCwEI,wExCxEJ,wBAAA,mCAYA,0BAAA,EwCiEI,kDACE,WAAA,EAGF,4DACE,iBAAA,kCACA,kBAAA,EAEA,mEACE,YAAA,6CACA,kBAAA,mCjCtFR,0BiC8DA,2BACE,eAAA,IAGE,yExCvDJ,0BAAA,mCAZA,wBAAA,EwCwEI,yExCxEJ,wBAAA,mCAYA,0BAAA,EwCiEI,mDACE,WAAA,EAGF,6DACE,iBAAA,kCACA,kBAAA,EAEA,oEACE,YAAA,6CACA,kBAAA,mCAcZ,kBxChJI,cAAA,EwCmJF,mCACE,aAAA,EAAA,EAAA,kCAEA,8CACE,oBAAA,ECtKJ,yBACE,MAAA,QACA,iBAAA,QAGE,sDAAA,sDAEE,MAAA,QACA,iBAAA,QAGF,uDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,2BACE,MAAA,QACA,iBAAA,QAGE,wDAAA,wDAEE,MAAA,QACA,iBAAA,QAGF,yDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,yBACE,MAAA,QACA,iBAAA,QAGE,sDAAA,sDAEE,MAAA,QACA,iBAAA,QAGF,uDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,sBACE,MAAA,QACA,iBAAA,QAGE,mDAAA,mDAEE,MAAA,QACA,iBAAA,QAGF,oDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,yBACE,MAAA,QACA,iBAAA,QAGE,sDAAA,sDAEE,MAAA,QACA,iBAAA,QAGF,uDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,wBACE,MAAA,QACA,iBAAA,QAGE,qDAAA,qDAEE,MAAA,QACA,iBAAA,QAGF,sDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,uBACE,MAAA,QACA,iBAAA,QAGE,oDAAA,oDAEE,MAAA,QACA,iBAAA,QAGF,qDACE,MAAA,KACA,iBAAA,QACA,aAAA,QAdN,sBACE,MAAA,QACA,iBAAA,QAGE,mDAAA,mDAEE,MAAA,QACA,iBAAA,QAGF,oDACE,MAAA,KACA,iBAAA,QACA,aAAA,QCbR,WACE,WAAA,YACA,MAAA,IACA,OAAA,IACA,QAAA,MAAA,MACA,MAAA,KACA,WAAA,YAAA,kUAAA,MAAA,CAAA,IAAA,KAAA,UACA,OAAA,E1COE,cAAA,Q0CLF,QAAA,GAGA,iBACE,MAAA,KACA,gBAAA,KACA,QAAA,IAGF,iBACE,QAAA,EACA,WAAA,EAAA,EAAA,EAAA,OAAA,qBACA,QAAA,EAGF,oBAAA,oBAEE,eAAA,KACA,oBAAA,KAAA,iBAAA,KAAA,YAAA,KACA,QAAA,IAIJ,iBACE,OAAA,UAAA,gBAAA,iBCtCF,OAEE,kBAAA,KACA,qBAAA,QACA,qBAAA,OACA,mBAAA,OACA,qBAAA,M9C+RI,qBAAA,S8C7RJ,iBAAA,EACA,cAAA,0BACA,wBAAA,IACA,wBAAA,mCACA,yBAAA,SACA,sBAAA,EAAA,OAAA,KAAA,oBACA,wBAAA,QACA,qBAAA,0BACA,+BAAA,oBAGA,MAAA,0BACA,UAAA,K9CiRI,UAAA,0B8C/QJ,MAAA,sBACA,eAAA,KACA,iBAAA,mBACA,gBAAA,YACA,OAAA,6BAAA,MAAA,6BACA,WAAA,2B3CRE,cAAA,8B2CWF,eACE,QAAA,EAGF,kBACE,QAAA,KAIJ,iBACE,kBAAA,KAEA,SAAA,SACA,QAAA,uBACA,MAAA,oBAAA,MAAA,iBAAA,MAAA,YACA,UAAA,KACA,eAAA,KAEA,mCACE,cAAA,wBAIJ,cACE,QAAA,KACA,YAAA,OACA,QAAA,0BAAA,0BACA,MAAA,6BACA,iBAAA,0BACA,gBAAA,YACA,cAAA,6BAAA,MAAA,oC3ChCE,uBAAA,mEACA,wBAAA,mE2CkCF,yBACE,aAAA,sCACA,YAAA,0BAIJ,YACE,QAAA,0BACA,UAAA,WC9DF,OAEE,kBAAA,KACA,iBAAA,MACA,mBAAA,KACA,kBAAA,OACA,iBAAA,EACA,cAAA,KACA,wBAAA,mCACA,wBAAA,IACA,yBAAA,OACA,sBAAA,EAAA,SAAA,QAAA,qBACA,+BAAA,mBACA,4BAAA,KACA,4BAAA,KACA,0BAAA,KAAA,KACA,+BAAA,uBACA,+BAAA,IACA,6BAAA,IACA,sBAAA,OACA,qBAAA,EACA,+BAAA,uBACA,+BAAA,IAGA,SAAA,MACA,IAAA,EACA,KAAA,EACA,QAAA,uBACA,QAAA,KACA,MAAA,KACA,OAAA,KACA,WAAA,OACA,WAAA,KAGA,QAAA,EAOF,cACE,SAAA,SACA,MAAA,KACA,OAAA,uBAEA,eAAA,KAGA,0B7B5CI,WAAA,UAAA,IAAA,S6B8CF,UAAA,mB7B1CE,uC6BwCJ,0B7BvCM,WAAA,M6B2CN,0BACE,UAAA,KAIF,kCACE,UAAA,YAIJ,yBACE,OAAA,wCAEA,wCACE,WAAA,KACA,SAAA,OAGF,qCACE,WAAA,KAIJ,uBACE,QAAA,KACA,YAAA,OACA,WAAA,wCAIF,eACE,SAAA,SACA,QAAA,KACA,eAAA,OACA,MAAA,KAEA,MAAA,sBACA,eAAA,KACA,iBAAA,mBACA,gBAAA,YACA,OAAA,6BAAA,MAAA,6B5CrFE,cAAA,8B4CyFF,QAAA,EAIF,gBAEE,qBAAA,KACA,iBAAA,KACA,sBAAA,IClHA,SAAA,MACA,IAAA,EACA,KAAA,EACA,QAAA,0BACA,MAAA,MACA,OAAA,MACA,iBAAA,sBAGA,qBAAS,QAAA,EACT,qBAAS,QAAA,2BDgHX,cACE,QAAA,KACA,YAAA,EACA,YAAA,OACA,gBAAA,cACA,QAAA,+BACA,cAAA,oCAAA,MAAA,oC5CtGE,uBAAA,oCACA,wBAAA,oC4CwGF,yBACE,QAAA,4CAAA,4CACA,OAAA,6CAAA,6CAAA,6CAAA,KAKJ,aACE,cAAA,EACA,YAAA,kCAKF,YACE,SAAA,SAGA,KAAA,EAAA,EAAA,KACA,QAAA,wBAIF,cACE,QAAA,KACA,YAAA,EACA,UAAA,KACA,YAAA,OACA,gBAAA,SACA,QAAA,gEACA,iBAAA,0BACA,WAAA,oCAAA,MAAA,oC5C1HE,2BAAA,oCACA,0BAAA,oC4C+HF,gBACE,OAAA,sCrC5GA,yBqCkHF,OACE,kBAAA,QACA,sBAAA,EAAA,OAAA,KAAA,oBAIF,cACE,UAAA,sBACA,aAAA,KACA,YAAA,KAGF,UACE,iBAAA,OrC/HA,yBqCoIF,U7CwnKF,U6CtnKI,iBAAA,OrCtIA,0BqC2IF,UACE,iBAAA,QAUA,kBACE,MAAA,MACA,UAAA,KACA,OAAA,KACA,OAAA,EAEA,iCACE,OAAA,KACA,OAAA,E5C1MJ,cAAA,ED6zKJ,gC6C/mKM,gC5C9MF,cAAA,E4CmNE,8BACE,WAAA,KrC3JJ,4BqCyIA,0BACE,MAAA,MACA,UAAA,KACA,OAAA,KACA,OAAA,EAEA,yCACE,OAAA,KACA,OAAA,E5C1MJ,cAAA,EDi1KJ,wC6CnoKM,wC5C9MF,cAAA,E4CmNE,sCACE,WAAA,MrC3JJ,4BqCyIA,0BACE,MAAA,MACA,UAAA,KACA,OAAA,KACA,OAAA,EAEA,yCACE,OAAA,KACA,OAAA,E5C1MJ,cAAA,EDq2KJ,wC6CvpKM,wC5C9MF,cAAA,E4CmNE,sCACE,WAAA,MrC3JJ,4BqCyIA,0BACE,MAAA,MACA,UAAA,KACA,OAAA,KACA,OAAA,EAEA,yCACE,OAAA,KACA,OAAA,E5C1MJ,cAAA,EDy3KJ,wC6C3qKM,wC5C9MF,cAAA,E4CmNE,sCACE,WAAA,MrC3JJ,6BqCyIA,0BACE,MAAA,MACA,UAAA,KACA,OAAA,KACA,OAAA,EAEA,yCACE,OAAA,KACA,OAAA,E5C1MJ,cAAA,ED64KJ,wC6C/rKM,wC5C9MF,cAAA,E4CmNE,sCACE,WAAA,MrC3JJ,6BqCyIA,2BACE,MAAA,MACA,UAAA,KACA,OAAA,KACA,OAAA,EAEA,0CACE,OAAA,KACA,OAAA,E5C1MJ,cAAA,EDi6KJ,yC6CntKM,yC5C9MF,cAAA,E4CmNE,uCACE,WAAA,MEtOR,SAEE,oBAAA,KACA,uBAAA,MACA,uBAAA,OACA,uBAAA,QACA,oBAAA,EjD8RI,uBAAA,SiD5RJ,mBAAA,KACA,gBAAA,KACA,2BAAA,SACA,qBAAA,IACA,yBAAA,OACA,0BAAA,OAGA,QAAA,yBACA,QAAA,MACA,QAAA,+BACA,OAAA,yBCnBA,YAAA,0BAEA,WAAA,OACA,YAAA,IACA,YAAA,IACA,WAAA,KACA,WAAA,MACA,gBAAA,KACA,YAAA,KACA,eAAA,KACA,eAAA,OACA,WAAA,OACA,YAAA,OACA,aAAA,OACA,WAAA,KlDsRI,UAAA,4BiD1QJ,UAAA,WACA,QAAA,EAEA,cAAS,QAAA,0BAET,wBACE,QAAA,MACA,MAAA,8BACA,OAAA,+BAEA,gCACE,SAAA,SACA,QAAA,GACA,aAAA,YACA,aAAA,MAKN,4DAAA,+BACE,OAAA,EAEA,oEAAA,uCACE,IAAA,KACA,aAAA,+BAAA,yCAAA,EACA,iBAAA,qBAKJ,8DAAA,+BACE,KAAA,EACA,MAAA,+BACA,OAAA,8BAEA,sEAAA,uCACE,MAAA,KACA,aAAA,yCAAA,+BAAA,yCAAA,EACA,mBAAA,qBAMJ,+DAAA,kCACE,IAAA,EAEA,uEAAA,0CACE,OAAA,KACA,aAAA,EAAA,yCAAA,+BACA,oBAAA,qBAKJ,6DAAA,iCACE,MAAA,EACA,MAAA,+BACA,OAAA,8BAEA,qEAAA,yCACE,KAAA,KACA,aAAA,yCAAA,EAAA,yCAAA,+BACA,kBAAA,qBAsBJ,eACE,UAAA,4BACA,QAAA,4BAAA,4BACA,MAAA,wBACA,WAAA,OACA,iBAAA,qB9ClGE,cAAA,gCgDnBJ,SAEE,oBAAA,KACA,uBAAA,MnDkSI,uBAAA,SmDhSJ,gBAAA,KACA,0BAAA,IACA,0BAAA,mCACA,2BAAA,OACA,iCAAA,mBACA,wBAAA,EAAA,OAAA,KAAA,oBACA,8BAAA,KACA,8BAAA,OnDyRI,8BAAA,KmDvRJ,0BAAA,EACA,uBAAA,QACA,4BAAA,KACA,4BAAA,KACA,wBAAA,QACA,yBAAA,KACA,0BAAA,OACA,0BAAA,+BAGA,QAAA,yBACA,QAAA,MACA,UAAA,4BDzBA,YAAA,0BAEA,WAAA,OACA,YAAA,IACA,YAAA,IACA,WAAA,KACA,WAAA,MACA,gBAAA,KACA,YAAA,KACA,eAAA,KACA,eAAA,OACA,WAAA,OACA,YAAA,OACA,aAAA,OACA,WAAA,KlDsRI,UAAA,4BmDrQJ,UAAA,WACA,iBAAA,qBACA,gBAAA,YACA,OAAA,+BAAA,MAAA,+BhDhBE,cAAA,gCgDoBF,wBACE,QAAA,MACA,MAAA,8BACA,OAAA,+BAEA,+BAAA,gCAEE,SAAA,SACA,QAAA,MACA,QAAA,GACA,aAAA,YACA,aAAA,MACA,aAAA,EAMJ,4DAAA,+BACE,OAAA,6EAEA,mEAAA,oEAAA,sCAAA,uCAEE,aAAA,+BAAA,yCAAA,EAGF,oEAAA,uCACE,OAAA,EACA,iBAAA,+BAGF,mEAAA,sCACE,OAAA,+BACA,iBAAA,qBAOJ,8DAAA,+BACE,KAAA,6EACA,MAAA,+BACA,OAAA,8BAEA,qEAAA,sEAAA,sCAAA,uCAEE,aAAA,yCAAA,+BAAA,yCAAA,EAGF,sEAAA,uCACE,KAAA,EACA,mBAAA,+BAGF,qEAAA,sCACE,KAAA,+BACA,mBAAA,qBAQJ,+DAAA,kCACE,IAAA,6EAEA,sEAAA,uEAAA,yCAAA,0CAEE,aAAA,EAAA,yCAAA,+BAGF,uEAAA,0CACE,IAAA,EACA,oBAAA,+BAGF,sEAAA,yCACE,IAAA,+BACA,oBAAA,qBAKJ,wEAAA,2CACE,SAAA,SACA,IAAA,EACA,KAAA,IACA,QAAA,MACA,MAAA,8BACA,YAAA,0CACA,QAAA,GACA,cAAA,+BAAA,MAAA,4BAMF,6DAAA,iCACE,MAAA,6EACA,MAAA,+BACA,OAAA,8BAEA,oEAAA,qEAAA,wCAAA,yCAEE,aAAA,yCAAA,EAAA,yCAAA,+BAGF,qEAAA,yCACE,MAAA,EACA,kBAAA,+BAGF,oEAAA,wCACE,MAAA,+BACA,kBAAA,qBAuBN,gBACE,QAAA,mCAAA,mCACA,cAAA,EnDiHI,UAAA,mCmD/GJ,MAAA,+BACA,iBAAA,4BACA,cAAA,+BAAA,MAAA,+BhD5JE,uBAAA,sCACA,wBAAA,sCgD8JF,sBACE,QAAA,KAIJ,cACE,QAAA,iCAAA,iCACA,MAAA,6BCrLF,UACE,SAAA,SAGF,wBACE,aAAA,MAGF,gBACE,SAAA,SACA,MAAA,KACA,SAAA,OCtBA,uBACE,QAAA,MACA,MAAA,KACA,QAAA,GDuBJ,eACE,SAAA,SACA,QAAA,KACA,MAAA,KACA,MAAA,KACA,aAAA,MACA,4BAAA,OAAA,oBAAA,OlClBI,WAAA,UAAA,IAAA,YAIA,uCkCQN,elCPQ,WAAA,MhB6sLR,oBACA,oBkD7rLA,sBAGE,QAAA,MlD+rLF,0BkD5rLA,8CAEE,UAAA,iBlD+rLF,4BkD5rLA,4CAEE,UAAA,kBASA,8BACE,QAAA,EACA,oBAAA,QACA,UAAA,KlDwrLJ,uDACA,qDkDtrLE,qCAGE,QAAA,EACA,QAAA,ElDurLJ,yCkDprLE,2CAEE,QAAA,EACA,QAAA,ElC5DE,WAAA,QAAA,GAAA,IAIA,uChBgvLN,yCkD3rLE,2ClCpDM,WAAA,MhBqvLR,uBkDprLA,uBAEE,SAAA,SACA,IAAA,EACA,OAAA,EACA,QAAA,EAEA,QAAA,KACA,YAAA,OACA,gBAAA,OACA,MAAA,IACA,QAAA,EACA,MAAA,KACA,WAAA,OACA,WAAA,IACA,OAAA,EACA,QAAA,GlCtFI,WAAA,QAAA,KAAA,KAIA,uChBywLN,uBkDvsLA,uBlCjEQ,WAAA,MhB8wLR,6BADA,6BkDxrLE,6BAAA,6BAEE,MAAA,KACA,gBAAA,KACA,QAAA,EACA,QAAA,GAGJ,uBACE,KAAA,EAGF,uBACE,MAAA,ElD4rLF,4BkDvrLA,4BAEE,QAAA,aACA,MAAA,KACA,OAAA,KACA,kBAAA,UACA,oBAAA,IACA,gBAAA,KAAA,KAWF,4BACE,iBAAA,wPAEF,4BACE,iBAAA,yPAQF,qBACE,SAAA,SACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,EACA,QAAA,KACA,gBAAA,OACA,QAAA,EAEA,aAAA,IACA,cAAA,KACA,YAAA,IACA,WAAA,KAEA,sCACE,WAAA,YACA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,OAAA,IACA,QAAA,EACA,aAAA,IACA,YAAA,IACA,YAAA,OACA,OAAA,QACA,iBAAA,KACA,gBAAA,YACA,OAAA,EAEA,WAAA,KAAA,MAAA,YACA,cAAA,KAAA,MAAA,YACA,QAAA,GlCzKE,WAAA,QAAA,IAAA,KAIA,uCkCqJJ,sClCpJM,WAAA,MkCwKN,6BACE,QAAA,EASJ,kBACE,SAAA,SACA,MAAA,IACA,OAAA,QACA,KAAA,IACA,YAAA,QACA,eAAA,QACA,MAAA,KACA,WAAA,OlDkrLF,2CkD5qLE,2CAEE,OAAA,UAAA,eAGF,qDACE,iBAAA,KAGF,iCACE,MAAA,KlD6qLJ,gBoDx4LA,cAEE,QAAA,aACA,MAAA,wBACA,OAAA,yBACA,eAAA,iCAEA,cAAA,IACA,UAAA,kCAAA,OAAA,SAAA,iCAIF,0BACE,GAAK,UAAA,gBAIP,gBAEE,mBAAA,KACA,oBAAA,KACA,4BAAA,SACA,0BAAA,OACA,6BAAA,MACA,4BAAA,eAGA,OAAA,+BAAA,MAAA,aACA,mBAAA,YAGF,mBAEE,mBAAA,KACA,oBAAA,KACA,0BAAA,MASF,wBACE,GACE,UAAA,SAEF,IACE,QAAA,EACA,UAAA,MAKJ,cAEE,mBAAA,KACA,oBAAA,KACA,4BAAA,SACA,6BAAA,MACA,4BAAA,aAGA,iBAAA,aACA,QAAA,EAGF,iBACE,mBAAA,KACA,oBAAA,KAIA,uCACE,gBpDs3LJ,coDp3LM,6BAAA,MC/EN,WAAA,cAAA,cAAA,cAAA,cAAA,eAEE,sBAAA,KACA,qBAAA,MACA,sBAAA,KACA,yBAAA,KACA,yBAAA,KACA,qBAAA,EACA,kBAAA,KACA,4BAAA,IACA,4BAAA,mCACA,0BAAA,EAAA,SAAA,QAAA,qB7C+DE,4B6C9CF,cAEI,SAAA,MACA,OAAA,EACA,QAAA,2BACA,QAAA,KACA,eAAA,OACA,UAAA,KACA,MAAA,0BACA,WAAA,OACA,iBAAA,uBACA,gBAAA,YACA,QAAA,ErC1BA,WAAA,UAAA,IAAA,aAIA,gEqCUJ,crCTM,WAAA,MRuDJ,4B6C9BE,8BACE,IAAA,EACA,KAAA,EACA,MAAA,0BACA,aAAA,iCAAA,MAAA,iCACA,UAAA,mB7CyBJ,4B6CtBE,4BACE,IAAA,EACA,MAAA,EACA,MAAA,0BACA,YAAA,iCAAA,MAAA,iCACA,UAAA,kB7CiBJ,4B6CdE,4BACE,IAAA,EACA,MAAA,EACA,KAAA,EACA,OAAA,2BACA,WAAA,KACA,cAAA,iCAAA,MAAA,iCACA,UAAA,mB7COJ,4B6CJE,+BACE,MAAA,EACA,KAAA,EACA,OAAA,2BACA,WAAA,KACA,WAAA,iCAAA,MAAA,iCACA,UAAA,kB7CFJ,4B6CKE,gCAAA,sBAEE,UAAA,M7CPJ,4B6CUE,qBAAA,mBAAA,sBAGE,WAAA,S7C1BJ,yB6CjCF,cAiEM,sBAAA,KACA,4BAAA,EACA,iBAAA,sBAEA,gCACE,QAAA,KAGF,8BACE,QAAA,KACA,UAAA,EACA,QAAA,EACA,WAAA,QAEA,iBAAA,uB7CjCN,4B6C9CF,cAEI,SAAA,MACA,OAAA,EACA,QAAA,2BACA,QAAA,KACA,eAAA,OACA,UAAA,KACA,MAAA,0BACA,WAAA,OACA,iBAAA,uBACA,gBAAA,YACA,QAAA,ErC1BA,WAAA,UAAA,IAAA,aAIA,gEqCUJ,crCTM,WAAA,MRuDJ,4B6C9BE,8BACE,IAAA,EACA,KAAA,EACA,MAAA,0BACA,aAAA,iCAAA,MAAA,iCACA,UAAA,mB7CyBJ,4B6CtBE,4BACE,IAAA,EACA,MAAA,EACA,MAAA,0BACA,YAAA,iCAAA,MAAA,iCACA,UAAA,kB7CiBJ,4B6CdE,4BACE,IAAA,EACA,MAAA,EACA,KAAA,EACA,OAAA,2BACA,WAAA,KACA,cAAA,iCAAA,MAAA,iCACA,UAAA,mB7COJ,4B6CJE,+BACE,MAAA,EACA,KAAA,EACA,OAAA,2BACA,WAAA,KACA,WAAA,iCAAA,MAAA,iCACA,UAAA,kB7CFJ,4B6CKE,gCAAA,sBAEE,UAAA,M7CPJ,4B6CUE,qBAAA,mBAAA,sBAGE,WAAA,S7C1BJ,yB6CjCF,cAiEM,sBAAA,KACA,4BAAA,EACA,iBAAA,sBAEA,gCACE,QAAA,KAGF,8BACE,QAAA,KACA,UAAA,EACA,QAAA,EACA,WAAA,QAEA,iBAAA,uB7CjCN,4B6C9CF,cAEI,SAAA,MACA,OAAA,EACA,QAAA,2BACA,QAAA,KACA,eAAA,OACA,UAAA,KACA,MAAA,0BACA,WAAA,OACA,iBAAA,uBACA,gBAAA,YACA,QAAA,ErC1BA,WAAA,UAAA,IAAA,aAIA,gEqCUJ,crCTM,WAAA,MRuDJ,4B6C9BE,8BACE,IAAA,EACA,KAAA,EACA,MAAA,0BACA,aAAA,iCAAA,MAAA,iCACA,UAAA,mB7CyBJ,4B6CtBE,4BACE,IAAA,EACA,MAAA,EACA,MAAA,0BACA,YAAA,iCAAA,MAAA,iCACA,UAAA,kB7CiBJ,4B6CdE,4BACE,IAAA,EACA,MAAA,EACA,KAAA,EACA,OAAA,2BACA,WAAA,KACA,cAAA,iCAAA,MAAA,iCACA,UAAA,mB7COJ,4B6CJE,+BACE,MAAA,EACA,KAAA,EACA,OAAA,2BACA,WAAA,KACA,WAAA,iCAAA,MAAA,iCACA,UAAA,kB7CFJ,4B6CKE,gCAAA,sBAEE,UAAA,M7CPJ,4B6CUE,qBAAA,mBAAA,sBAGE,WAAA,S7C1BJ,yB6CjCF,cAiEM,sBAAA,KACA,4BAAA,EACA,iBAAA,sBAEA,gCACE,QAAA,KAGF,8BACE,QAAA,KACA,UAAA,EACA,QAAA,EACA,WAAA,QAEA,iBAAA,uB7CjCN,6B6C9CF,cAEI,SAAA,MACA,OAAA,EACA,QAAA,2BACA,QAAA,KACA,eAAA,OACA,UAAA,KACA,MAAA,0BACA,WAAA,OACA,iBAAA,uBACA,gBAAA,YACA,QAAA,ErC1BA,WAAA,UAAA,IAAA,aAIA,iEqCUJ,crCTM,WAAA,MRuDJ,6B6C9BE,8BACE,IAAA,EACA,KAAA,EACA,MAAA,0BACA,aAAA,iCAAA,MAAA,iCACA,UAAA,mB7CyBJ,6B6CtBE,4BACE,IAAA,EACA,MAAA,EACA,MAAA,0BACA,YAAA,iCAAA,MAAA,iCACA,UAAA,kB7CiBJ,6B6CdE,4BACE,IAAA,EACA,MAAA,EACA,KAAA,EACA,OAAA,2BACA,WAAA,KACA,cAAA,iCAAA,MAAA,iCACA,UAAA,mB7COJ,6B6CJE,+BACE,MAAA,EACA,KAAA,EACA,OAAA,2BACA,WAAA,KACA,WAAA,iCAAA,MAAA,iCACA,UAAA,kB7CFJ,6B6CKE,gCAAA,sBAEE,UAAA,M7CPJ,6B6CUE,qBAAA,mBAAA,sBAGE,WAAA,S7C1BJ,0B6CjCF,cAiEM,sBAAA,KACA,4BAAA,EACA,iBAAA,sBAEA,gCACE,QAAA,KAGF,8BACE,QAAA,KACA,UAAA,EACA,QAAA,EACA,WAAA,QAEA,iBAAA,uB7CjCN,6B6C9CF,eAEI,SAAA,MACA,OAAA,EACA,QAAA,2BACA,QAAA,KACA,eAAA,OACA,UAAA,KACA,MAAA,0BACA,WAAA,OACA,iBAAA,uBACA,gBAAA,YACA,QAAA,ErC1BA,WAAA,UAAA,IAAA,aAIA,iEqCUJ,erCTM,WAAA,MRuDJ,6B6C9BE,+BACE,IAAA,EACA,KAAA,EACA,MAAA,0BACA,aAAA,iCAAA,MAAA,iCACA,UAAA,mB7CyBJ,6B6CtBE,6BACE,IAAA,EACA,MAAA,EACA,MAAA,0BACA,YAAA,iCAAA,MAAA,iCACA,UAAA,kB7CiBJ,6B6CdE,6BACE,IAAA,EACA,MAAA,EACA,KAAA,EACA,OAAA,2BACA,WAAA,KACA,cAAA,iCAAA,MAAA,iCACA,UAAA,mB7COJ,6B6CJE,gCACE,MAAA,EACA,KAAA,EACA,OAAA,2BACA,WAAA,KACA,WAAA,iCAAA,MAAA,iCACA,UAAA,kB7CFJ,6B6CKE,iCAAA,uBAEE,UAAA,M7CPJ,6B6CUE,sBAAA,oBAAA,uBAGE,WAAA,S7C1BJ,0B6CjCF,eAiEM,sBAAA,KACA,4BAAA,EACA,iBAAA,sBAEA,iCACE,QAAA,KAGF,+BACE,QAAA,KACA,UAAA,EACA,QAAA,EACA,WAAA,QAEA,iBAAA,uBA/ER,WAEI,SAAA,MACA,OAAA,EACA,QAAA,2BACA,QAAA,KACA,eAAA,OACA,UAAA,KACA,MAAA,0BACA,WAAA,OACA,iBAAA,uBACA,gBAAA,YACA,QAAA,ErC1BA,WAAA,UAAA,IAAA,YAIA,uCqCUJ,WrCTM,WAAA,MqCyBF,2BACE,IAAA,EACA,KAAA,EACA,MAAA,0BACA,aAAA,iCAAA,MAAA,iCACA,UAAA,kBAGF,yBACE,IAAA,EACA,MAAA,EACA,MAAA,0BACA,YAAA,iCAAA,MAAA,iCACA,UAAA,iBAGF,yBACE,IAAA,EACA,MAAA,EACA,KAAA,EACA,OAAA,2BACA,WAAA,KACA,cAAA,iCAAA,MAAA,iCACA,UAAA,kBAGF,4BACE,MAAA,EACA,KAAA,EACA,OAAA,2BACA,WAAA,KACA,WAAA,iCAAA,MAAA,iCACA,UAAA,iBAGF,6BAAA,mBAEE,UAAA,KAGF,kBAAA,gBAAA,mBAGE,WAAA,QA2BR,oBPlHE,SAAA,MACA,IAAA,EACA,KAAA,EACA,QAAA,KACA,MAAA,MACA,OAAA,MACA,iBAAA,KAGA,yBAAS,QAAA,EACT,yBAAS,QAAA,GO4GX,kBACE,QAAA,KACA,YAAA,OACA,gBAAA,cACA,QAAA,8BAAA,8BAEA,6BACE,QAAA,yCAAA,yCACA,WAAA,0CACA,aAAA,0CACA,cAAA,0CAIJ,iBACE,cAAA,EACA,YAAA,IAGF,gBACE,UAAA,EACA,QAAA,8BAAA,8BACA,WAAA,KC9IF,aACE,QAAA,aACA,WAAA,IACA,eAAA,OACA,OAAA,KACA,iBAAA,aACA,QAAA,GAEA,yBACE,QAAA,aACA,QAAA,GAKJ,gBACE,WAAA,KAGF,gBACE,WAAA,KAGF,gBACE,WAAA,MAKA,+BACE,UAAA,iBAAA,GAAA,YAAA,SAIJ,4BACE,IACE,QAAA,IAIJ,kBACE,mBAAA,8DAAA,WAAA,8DACA,kBAAA,KAAA,KAAA,UAAA,KAAA,KACA,UAAA,iBAAA,GAAA,OAAA,SAGF,4BACE,KACE,sBAAA,MAAA,GAAA,cAAA,MAAA,IH9CF,iBACE,QAAA,MACA,MAAA,KACA,QAAA,GIAF,iBACE,MAAA,eACA,iBAAA,kDAFF,mBACE,MAAA,eACA,iBAAA,mDAFF,iBACE,MAAA,eACA,iBAAA,iDAFF,cACE,MAAA,eACA,iBAAA,kDAFF,iBACE,MAAA,eACA,iBAAA,iDAFF,gBACE,MAAA,eACA,iBAAA,iDAFF,eACE,MAAA,eACA,iBAAA,mDAFF,cACE,MAAA,eACA,iBAAA,gDCNF,cACE,MAAA,kBAGE,oBAAA,oBAEE,MAAA,kBANN,gBACE,MAAA,kBAGE,sBAAA,sBAEE,MAAA,kBANN,cACE,MAAA,kBAGE,oBAAA,oBAEE,MAAA,kBANN,WACE,MAAA,kBAGE,iBAAA,iBAEE,MAAA,kBANN,cACE,MAAA,kBAGE,oBAAA,oBAEE,MAAA,kBANN,aACE,MAAA,kBAGE,mBAAA,mBAEE,MAAA,kBANN,YACE,MAAA,kBAGE,kBAAA,kBAEE,MAAA,kBANN,WACE,MAAA,kBAGE,iBAAA,iBAEE,MAAA,kBCLR,OACE,SAAA,SACA,MAAA,KAEA,eACE,QAAA,MACA,YAAA,uBACA,QAAA,GAGF,SACE,SAAA,SACA,IAAA,EACA,KAAA,EACA,MAAA,KACA,OAAA,KAKF,WACE,kBAAA,KADF,WACE,kBAAA,IADF,YACE,kBAAA,OADF,YACE,kBAAA,eCrBJ,WACE,SAAA,MACA,IAAA,EACA,MAAA,EACA,KAAA,EACA,QAAA,KAGF,cACE,SAAA,MACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,KAQE,YACE,SAAA,eAAA,SAAA,OACA,IAAA,EACA,QAAA,KAGF,eACE,SAAA,eAAA,SAAA,OACA,OAAA,EACA,QAAA,KlD+BF,yBkDxCA,eACE,SAAA,eAAA,SAAA,OACA,IAAA,EACA,QAAA,KAGF,kBACE,SAAA,eAAA,SAAA,OACA,OAAA,EACA,QAAA,MlD+BF,yBkDxCA,eACE,SAAA,eAAA,SAAA,OACA,IAAA,EACA,QAAA,KAGF,kBACE,SAAA,eAAA,SAAA,OACA,OAAA,EACA,QAAA,MlD+BF,yBkDxCA,eACE,SAAA,eAAA,SAAA,OACA,IAAA,EACA,QAAA,KAGF,kBACE,SAAA,eAAA,SAAA,OACA,OAAA,EACA,QAAA,MlD+BF,0BkDxCA,eACE,SAAA,eAAA,SAAA,OACA,IAAA,EACA,QAAA,KAGF,kBACE,SAAA,eAAA,SAAA,OACA,OAAA,EACA,QAAA,MlD+BF,0BkDxCA,gBACE,SAAA,eAAA,SAAA,OACA,IAAA,EACA,QAAA,KAGF,mBACE,SAAA,eAAA,SAAA,OACA,OAAA,EACA,QAAA,MC/BN,QACE,QAAA,KACA,eAAA,IACA,YAAA,OACA,WAAA,QAGF,QACE,QAAA,KACA,KAAA,EAAA,EAAA,KACA,eAAA,OACA,WAAA,QCRF,iB5DqxNA,0D6DjxNE,SAAA,mBACA,MAAA,cACA,OAAA,cACA,QAAA,YACA,OAAA,eACA,SAAA,iBACA,KAAA,wBACA,YAAA,iBACA,OAAA,YCXA,uBACE,SAAA,SACA,IAAA,EACA,MAAA,EACA,OAAA,EACA,KAAA,EACA,QAAA,EACA,QAAA,GCRJ,eCAE,SAAA,OACA,cAAA,SACA,YAAA,OCNF,IACE,QAAA,aACA,WAAA,QACA,MAAA,IACA,WAAA,IACA,iBAAA,aACA,QAAA,IC4DM,gBAOI,eAAA,mBAPJ,WAOI,eAAA,cAPJ,cAOI,eAAA,iBAPJ,cAOI,eAAA,iBAPJ,mBAOI,eAAA,sBAPJ,gBAOI,eAAA,mBAPJ,aAOI,MAAA,eAPJ,WAOI,MAAA,gBAPJ,YAOI,MAAA,eAPJ,WAOI,QAAA,YAPJ,YAOI,QAAA,cAPJ,YAOI,QAAA,aAPJ,YAOI,QAAA,cAPJ,aAOI,QAAA,YAPJ,eAOI,SAAA,eAPJ,iBAOI,SAAA,iBAPJ,kBAOI,SAAA,kBAPJ,iBAOI,SAAA,iBAPJ,UAOI,QAAA,iBAPJ,gBAOI,QAAA,uBAPJ,SAOI,QAAA,gBAPJ,QAOI,QAAA,eAPJ,SAOI,QAAA,gBAPJ,aAOI,QAAA,oBAPJ,cAOI,QAAA,qBAPJ,QAOI,QAAA,eAPJ,eAOI,QAAA,sBAPJ,QAOI,QAAA,eAPJ,QAOI,WAAA,EAAA,MAAA,KAAA,0BAPJ,WAOI,WAAA,EAAA,QAAA,OAAA,2BAPJ,WAOI,WAAA,EAAA,KAAA,KAAA,2BAPJ,aAOI,WAAA,eAPJ,iBAOI,SAAA,iBAPJ,mBAOI,SAAA,mBAPJ,mBAOI,SAAA,mBAPJ,gBAOI,SAAA,gBAPJ,iBAOI,SAAA,yBAAA,SAAA,iBAPJ,OAOI,IAAA,YAPJ,QAOI,IAAA,cAPJ,SAOI,IAAA,eAPJ,UAOI,OAAA,YAPJ,WAOI,OAAA,cAPJ,YAOI,OAAA,eAPJ,SAOI,KAAA,YAPJ,UAOI,KAAA,cAPJ,WAOI,KAAA,eAPJ,OAOI,MAAA,YAPJ,QAOI,MAAA,cAPJ,SAOI,MAAA,eAPJ,kBAOI,UAAA,+BAPJ,oBAOI,UAAA,2BAPJ,oBAOI,UAAA,2BAPJ,QAOI,OAAA,uBAAA,uBAAA,iCAPJ,UAOI,OAAA,YAPJ,YAOI,WAAA,uBAAA,uBAAA,iCAPJ,cAOI,WAAA,YAPJ,YAOI,aAAA,uBAAA,uBAAA,iCAPJ,cAOI,aAAA,YAPJ,eAOI,cAAA,uBAAA,uBAAA,iCAPJ,iBAOI,cAAA,YAPJ,cAOI,YAAA,uBAAA,uBAAA,iCAPJ,gBAOI,YAAA,YAPJ,gBAIQ,oBAAA,EAGJ,aAAA,+DAPJ,kBAIQ,oBAAA,EAGJ,aAAA,iEAPJ,gBAIQ,oBAAA,EAGJ,aAAA,+DAPJ,aAIQ,oBAAA,EAGJ,aAAA,4DAPJ,gBAIQ,oBAAA,EAGJ,aAAA,+DAPJ,eAIQ,oBAAA,EAGJ,aAAA,8DAPJ,cAIQ,oBAAA,EAGJ,aAAA,6DAPJ,aAIQ,oBAAA,EAGJ,aAAA,4DAPJ,cAIQ,oBAAA,EAGJ,aAAA,6DAjBJ,UACE,kBAAA,IADF,UACE,kBAAA,IADF,UACE,kBAAA,IADF,UACE,kBAAA,IADF,UACE,kBAAA,IADF,mBACE,oBAAA,IADF,mBACE,oBAAA,KADF,mBACE,oBAAA,IADF,mBACE,oBAAA,KADF,oBACE,oBAAA,EASF,MAOI,MAAA,cAPJ,MAOI,MAAA,cAPJ,MAOI,MAAA,cAPJ,OAOI,MAAA,eAPJ,QAOI,MAAA,eAPJ,QAOI,UAAA,eAPJ,QAOI,MAAA,gBAPJ,YAOI,UAAA,gBAPJ,MAOI,OAAA,cAPJ,MAOI,OAAA,cAPJ,MAOI,OAAA,cAPJ,OAOI,OAAA,eAPJ,QAOI,OAAA,eAPJ,QAOI,WAAA,eAPJ,QAOI,OAAA,gBAPJ,YAOI,WAAA,gBAPJ,WAOI,KAAA,EAAA,EAAA,eAPJ,UAOI,eAAA,cAPJ,aAOI,eAAA,iBAPJ,kBAOI,eAAA,sBAPJ,qBAOI,eAAA,yBAPJ,aAOI,UAAA,YAPJ,aAOI,UAAA,YAPJ,eAOI,YAAA,YAPJ,eAOI,YAAA,YAPJ,WAOI,UAAA,eAPJ,aAOI,UAAA,iBAPJ,mBAOI,UAAA,uBAPJ,uBAOI,gBAAA,qBAPJ,qBAOI,gBAAA,mBAPJ,wBAOI,gBAAA,iBAPJ,yBAOI,gBAAA,wBAPJ,wBAOI,gBAAA,uBAPJ,wBAOI,gBAAA,uBAPJ,mBAOI,YAAA,qBAPJ,iBAOI,YAAA,mBAPJ,oBAOI,YAAA,iBAPJ,sBAOI,YAAA,mBAPJ,qBAOI,YAAA,kBAPJ,qBAOI,cAAA,qBAPJ,mBAOI,cAAA,mBAPJ,sBAOI,cAAA,iBAPJ,uBAOI,cAAA,wBAPJ,sBAOI,cAAA,uBAPJ,uBAOI,cAAA,kBAPJ,iBAOI,WAAA,eAPJ,kBAOI,WAAA,qBAPJ,gBAOI,WAAA,mBAPJ,mBAOI,WAAA,iBAPJ,qBAOI,WAAA,mBAPJ,oBAOI,WAAA,kBAPJ,aAOI,MAAA,aAPJ,SAOI,MAAA,YAPJ,SAOI,MAAA,YAPJ,SAOI,MAAA,YAPJ,SAOI,MAAA,YAPJ,SAOI,MAAA,YAPJ,SAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,KAOI,OAAA,YAPJ,KAOI,OAAA,iBAPJ,KAOI,OAAA,gBAPJ,KAOI,OAAA,eAPJ,KAOI,OAAA,iBAPJ,KAOI,OAAA,eAPJ,QAOI,OAAA,eAPJ,MAOI,aAAA,YAAA,YAAA,YAPJ,MAOI,aAAA,iBAAA,YAAA,iBAPJ,MAOI,aAAA,gBAAA,YAAA,gBAPJ,MAOI,aAAA,eAAA,YAAA,eAPJ,MAOI,aAAA,iBAAA,YAAA,iBAPJ,MAOI,aAAA,eAAA,YAAA,eAPJ,SAOI,aAAA,eAAA,YAAA,eAPJ,MAOI,WAAA,YAAA,cAAA,YAPJ,MAOI,WAAA,iBAAA,cAAA,iBAPJ,MAOI,WAAA,gBAAA,cAAA,gBAPJ,MAOI,WAAA,eAAA,cAAA,eAPJ,MAOI,WAAA,iBAAA,cAAA,iBAPJ,MAOI,WAAA,eAAA,cAAA,eAPJ,SAOI,WAAA,eAAA,cAAA,eAPJ,MAOI,WAAA,YAPJ,MAOI,WAAA,iBAPJ,MAOI,WAAA,gBAPJ,MAOI,WAAA,eAPJ,MAOI,WAAA,iBAPJ,MAOI,WAAA,eAPJ,SAOI,WAAA,eAPJ,MAOI,aAAA,YAPJ,MAOI,aAAA,iBAPJ,MAOI,aAAA,gBAPJ,MAOI,aAAA,eAPJ,MAOI,aAAA,iBAPJ,MAOI,aAAA,eAPJ,SAOI,aAAA,eAPJ,MAOI,cAAA,YAPJ,MAOI,cAAA,iBAPJ,MAOI,cAAA,gBAPJ,MAOI,cAAA,eAPJ,MAOI,cAAA,iBAPJ,MAOI,cAAA,eAPJ,SAOI,cAAA,eAPJ,MAOI,YAAA,YAPJ,MAOI,YAAA,iBAPJ,MAOI,YAAA,gBAPJ,MAOI,YAAA,eAPJ,MAOI,YAAA,iBAPJ,MAOI,YAAA,eAPJ,SAOI,YAAA,eAPJ,KAOI,QAAA,YAPJ,KAOI,QAAA,iBAPJ,KAOI,QAAA,gBAPJ,KAOI,QAAA,eAPJ,KAOI,QAAA,iBAPJ,KAOI,QAAA,eAPJ,MAOI,cAAA,YAAA,aAAA,YAPJ,MAOI,cAAA,iBAAA,aAAA,iBAPJ,MAOI,cAAA,gBAAA,aAAA,gBAPJ,MAOI,cAAA,eAAA,aAAA,eAPJ,MAOI,cAAA,iBAAA,aAAA,iBAPJ,MAOI,cAAA,eAAA,aAAA,eAPJ,MAOI,YAAA,YAAA,eAAA,YAPJ,MAOI,YAAA,iBAAA,eAAA,iBAPJ,MAOI,YAAA,gBAAA,eAAA,gBAPJ,MAOI,YAAA,eAAA,eAAA,eAPJ,MAOI,YAAA,iBAAA,eAAA,iBAPJ,MAOI,YAAA,eAAA,eAAA,eAPJ,MAOI,YAAA,YAPJ,MAOI,YAAA,iBAPJ,MAOI,YAAA,gBAPJ,MAOI,YAAA,eAPJ,MAOI,YAAA,iBAPJ,MAOI,YAAA,eAPJ,MAOI,cAAA,YAPJ,MAOI,cAAA,iBAPJ,MAOI,cAAA,gBAPJ,MAOI,cAAA,eAPJ,MAOI,cAAA,iBAPJ,MAOI,cAAA,eAPJ,MAOI,eAAA,YAPJ,MAOI,eAAA,iBAPJ,MAOI,eAAA,gBAPJ,MAOI,eAAA,eAPJ,MAOI,eAAA,iBAPJ,MAOI,eAAA,eAPJ,MAOI,aAAA,YAPJ,MAOI,aAAA,iBAPJ,MAOI,aAAA,gBAPJ,MAOI,aAAA,eAPJ,MAOI,aAAA,iBAPJ,MAOI,aAAA,eAPJ,OAOI,IAAA,YAPJ,OAOI,IAAA,iBAPJ,OAOI,IAAA,gBAPJ,OAOI,IAAA,eAPJ,OAOI,IAAA,iBAPJ,OAOI,IAAA,eAPJ,gBAOI,YAAA,mCAPJ,MAOI,UAAA,iCAPJ,MAOI,UAAA,gCAPJ,MAOI,UAAA,8BAPJ,MAOI,UAAA,gCAPJ,MAOI,UAAA,kBAPJ,MAOI,UAAA,eAPJ,YAOI,WAAA,iBAPJ,YAOI,WAAA,iBAPJ,UAOI,YAAA,cAPJ,YAOI,YAAA,kBAPJ,WAOI,YAAA,cAPJ,SAOI,YAAA,cAPJ,aAOI,YAAA,cAPJ,WAOI,YAAA,iBAPJ,MAOI,YAAA,YAPJ,OAOI,YAAA,eAPJ,SAOI,YAAA,cAPJ,OAOI,YAAA,YAPJ,YAOI,WAAA,eAPJ,UAOI,WAAA,gBAPJ,aAOI,WAAA,iBAPJ,sBAOI,gBAAA,eAPJ,2BAOI,gBAAA,oBAPJ,8BAOI,gBAAA,uBAPJ,gBAOI,eAAA,oBAPJ,gBAOI,eAAA,oBAPJ,iBAOI,eAAA,qBAPJ,WAOI,YAAA,iBAPJ,aAOI,YAAA,iBAPJ,YAOI,UAAA,qBAAA,WAAA,qBAPJ,cAIQ,kBAAA,EAGJ,MAAA,6DAPJ,gBAIQ,kBAAA,EAGJ,MAAA,+DAPJ,cAIQ,kBAAA,EAGJ,MAAA,6DAPJ,WAIQ,kBAAA,EAGJ,MAAA,0DAPJ,cAIQ,kBAAA,EAGJ,MAAA,6DAPJ,aAIQ,kBAAA,EAGJ,MAAA,4DAPJ,YAIQ,kBAAA,EAGJ,MAAA,2DAPJ,WAIQ,kBAAA,EAGJ,MAAA,0DAPJ,YAIQ,kBAAA,EAGJ,MAAA,2DAPJ,YAIQ,kBAAA,EAGJ,MAAA,2DAPJ,WAIQ,kBAAA,EAGJ,MAAA,gEAPJ,YAIQ,kBAAA,EAGJ,MAAA,kBAPJ,eAIQ,kBAAA,EAGJ,MAAA,yBAPJ,eAIQ,kBAAA,EAGJ,MAAA,+BAPJ,YAIQ,kBAAA,EAGJ,MAAA,kBAjBJ,iBACE,kBAAA,KADF,iBACE,kBAAA,IADF,iBACE,kBAAA,KADF,kBACE,kBAAA,EASF,YAIQ,gBAAA,EAGJ,iBAAA,2DAPJ,cAIQ,gBAAA,EAGJ,iBAAA,6DAPJ,YAIQ,gBAAA,EAGJ,iBAAA,2DAPJ,SAIQ,gBAAA,EAGJ,iBAAA,wDAPJ,YAIQ,gBAAA,EAGJ,iBAAA,2DAPJ,WAIQ,gBAAA,EAGJ,iBAAA,0DAPJ,UAIQ,gBAAA,EAGJ,iBAAA,yDAPJ,SAIQ,gBAAA,EAGJ,iBAAA,wDAPJ,UAIQ,gBAAA,EAGJ,iBAAA,yDAPJ,UAIQ,gBAAA,EAGJ,iBAAA,yDAPJ,SAIQ,gBAAA,EAGJ,iBAAA,2DAPJ,gBAIQ,gBAAA,EAGJ,iBAAA,sBAjBJ,eACE,gBAAA,IADF,eACE,gBAAA,KADF,eACE,gBAAA,IADF,eACE,gBAAA,KADF,gBACE,gBAAA,EASF,aAOI,iBAAA,6BAPJ,iBAOI,oBAAA,cAAA,iBAAA,cAAA,YAAA,cAPJ,kBAOI,oBAAA,eAAA,iBAAA,eAAA,YAAA,eAPJ,kBAOI,oBAAA,eAAA,iBAAA,eAAA,YAAA,eAPJ,SAOI,eAAA,eAPJ,SAOI,eAAA,eAPJ,SAOI,cAAA,kCAPJ,WAOI,cAAA,YAPJ,WAOI,cAAA,qCAPJ,WAOI,cAAA,kCAPJ,WAOI,cAAA,qCAPJ,WAOI,cAAA,qCAPJ,WAOI,cAAA,sCAPJ,gBAOI,cAAA,cAPJ,cAOI,cAAA,uCAPJ,aAOI,uBAAA,kCAAA,wBAAA,kCAPJ,aAOI,wBAAA,kCAAA,2BAAA,kCAPJ,gBAOI,2BAAA,kCAAA,0BAAA,kCAPJ,eAOI,0BAAA,kCAAA,uBAAA,kCAPJ,SAOI,WAAA,kBAPJ,WAOI,WAAA,iB1DVR,yB0DGI,gBAOI,MAAA,eAPJ,cAOI,MAAA,gBAPJ,eAOI,MAAA,eAPJ,aAOI,QAAA,iBAPJ,mBAOI,QAAA,uBAPJ,YAOI,QAAA,gBAPJ,WAOI,QAAA,eAPJ,YAOI,QAAA,gBAPJ,gBAOI,QAAA,oBAPJ,iBAOI,QAAA,qBAPJ,WAOI,QAAA,eAPJ,kBAOI,QAAA,sBAPJ,WAOI,QAAA,eAPJ,cAOI,KAAA,EAAA,EAAA,eAPJ,aAOI,eAAA,cAPJ,gBAOI,eAAA,iBAPJ,qBAOI,eAAA,sBAPJ,wBAOI,eAAA,yBAPJ,gBAOI,UAAA,YAPJ,gBAOI,UAAA,YAPJ,kBAOI,YAAA,YAPJ,kBAOI,YAAA,YAPJ,cAOI,UAAA,eAPJ,gBAOI,UAAA,iBAPJ,sBAOI,UAAA,uBAPJ,0BAOI,gBAAA,qBAPJ,wBAOI,gBAAA,mBAPJ,2BAOI,gBAAA,iBAPJ,4BAOI,gBAAA,wBAPJ,2BAOI,gBAAA,uBAPJ,2BAOI,gBAAA,uBAPJ,sBAOI,YAAA,qBAPJ,oBAOI,YAAA,mBAPJ,uBAOI,YAAA,iBAPJ,yBAOI,YAAA,mBAPJ,wBAOI,YAAA,kBAPJ,wBAOI,cAAA,qBAPJ,sBAOI,cAAA,mBAPJ,yBAOI,cAAA,iBAPJ,0BAOI,cAAA,wBAPJ,yBAOI,cAAA,uBAPJ,0BAOI,cAAA,kBAPJ,oBAOI,WAAA,eAPJ,qBAOI,WAAA,qBAPJ,mBAOI,WAAA,mBAPJ,sBAOI,WAAA,iBAPJ,wBAOI,WAAA,mBAPJ,uBAOI,WAAA,kBAPJ,gBAOI,MAAA,aAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,eAOI,MAAA,YAPJ,QAOI,OAAA,YAPJ,QAOI,OAAA,iBAPJ,QAOI,OAAA,gBAPJ,QAOI,OAAA,eAPJ,QAOI,OAAA,iBAPJ,QAOI,OAAA,eAPJ,WAOI,OAAA,eAPJ,SAOI,aAAA,YAAA,YAAA,YAPJ,SAOI,aAAA,iBAAA,YAAA,iBAPJ,SAOI,aAAA,gBAAA,YAAA,gBAPJ,SAOI,aAAA,eAAA,YAAA,eAPJ,SAOI,aAAA,iBAAA,YAAA,iBAPJ,SAOI,aAAA,eAAA,YAAA,eAPJ,YAOI,aAAA,eAAA,YAAA,eAPJ,SAOI,WAAA,YAAA,cAAA,YAPJ,SAOI,WAAA,iBAAA,cAAA,iBAPJ,SAOI,WAAA,gBAAA,cAAA,gBAPJ,SAOI,WAAA,eAAA,cAAA,eAPJ,SAOI,WAAA,iBAAA,cAAA,iBAPJ,SAOI,WAAA,eAAA,cAAA,eAPJ,YAOI,WAAA,eAAA,cAAA,eAPJ,SAOI,WAAA,YAPJ,SAOI,WAAA,iBAPJ,SAOI,WAAA,gBAPJ,SAOI,WAAA,eAPJ,SAOI,WAAA,iBAPJ,SAOI,WAAA,eAPJ,YAOI,WAAA,eAPJ,SAOI,aAAA,YAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,gBAPJ,SAOI,aAAA,eAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,eAPJ,YAOI,aAAA,eAPJ,SAOI,cAAA,YAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,gBAPJ,SAOI,cAAA,eAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,eAPJ,YAOI,cAAA,eAPJ,SAOI,YAAA,YAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,gBAPJ,SAOI,YAAA,eAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,eAPJ,YAOI,YAAA,eAPJ,QAOI,QAAA,YAPJ,QAOI,QAAA,iBAPJ,QAOI,QAAA,gBAPJ,QAOI,QAAA,eAPJ,QAOI,QAAA,iBAPJ,QAOI,QAAA,eAPJ,SAOI,cAAA,YAAA,aAAA,YAPJ,SAOI,cAAA,iBAAA,aAAA,iBAPJ,SAOI,cAAA,gBAAA,aAAA,gBAPJ,SAOI,cAAA,eAAA,aAAA,eAPJ,SAOI,cAAA,iBAAA,aAAA,iBAPJ,SAOI,cAAA,eAAA,aAAA,eAPJ,SAOI,YAAA,YAAA,eAAA,YAPJ,SAOI,YAAA,iBAAA,eAAA,iBAPJ,SAOI,YAAA,gBAAA,eAAA,gBAPJ,SAOI,YAAA,eAAA,eAAA,eAPJ,SAOI,YAAA,iBAAA,eAAA,iBAPJ,SAOI,YAAA,eAAA,eAAA,eAPJ,SAOI,YAAA,YAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,gBAPJ,SAOI,YAAA,eAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,eAPJ,SAOI,cAAA,YAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,gBAPJ,SAOI,cAAA,eAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,eAPJ,SAOI,eAAA,YAPJ,SAOI,eAAA,iBAPJ,SAOI,eAAA,gBAPJ,SAOI,eAAA,eAPJ,SAOI,eAAA,iBAPJ,SAOI,eAAA,eAPJ,SAOI,aAAA,YAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,gBAPJ,SAOI,aAAA,eAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,eAPJ,UAOI,IAAA,YAPJ,UAOI,IAAA,iBAPJ,UAOI,IAAA,gBAPJ,UAOI,IAAA,eAPJ,UAOI,IAAA,iBAPJ,UAOI,IAAA,eAPJ,eAOI,WAAA,eAPJ,aAOI,WAAA,gBAPJ,gBAOI,WAAA,kB1DVR,yB0DGI,gBAOI,MAAA,eAPJ,cAOI,MAAA,gBAPJ,eAOI,MAAA,eAPJ,aAOI,QAAA,iBAPJ,mBAOI,QAAA,uBAPJ,YAOI,QAAA,gBAPJ,WAOI,QAAA,eAPJ,YAOI,QAAA,gBAPJ,gBAOI,QAAA,oBAPJ,iBAOI,QAAA,qBAPJ,WAOI,QAAA,eAPJ,kBAOI,QAAA,sBAPJ,WAOI,QAAA,eAPJ,cAOI,KAAA,EAAA,EAAA,eAPJ,aAOI,eAAA,cAPJ,gBAOI,eAAA,iBAPJ,qBAOI,eAAA,sBAPJ,wBAOI,eAAA,yBAPJ,gBAOI,UAAA,YAPJ,gBAOI,UAAA,YAPJ,kBAOI,YAAA,YAPJ,kBAOI,YAAA,YAPJ,cAOI,UAAA,eAPJ,gBAOI,UAAA,iBAPJ,sBAOI,UAAA,uBAPJ,0BAOI,gBAAA,qBAPJ,wBAOI,gBAAA,mBAPJ,2BAOI,gBAAA,iBAPJ,4BAOI,gBAAA,wBAPJ,2BAOI,gBAAA,uBAPJ,2BAOI,gBAAA,uBAPJ,sBAOI,YAAA,qBAPJ,oBAOI,YAAA,mBAPJ,uBAOI,YAAA,iBAPJ,yBAOI,YAAA,mBAPJ,wBAOI,YAAA,kBAPJ,wBAOI,cAAA,qBAPJ,sBAOI,cAAA,mBAPJ,yBAOI,cAAA,iBAPJ,0BAOI,cAAA,wBAPJ,yBAOI,cAAA,uBAPJ,0BAOI,cAAA,kBAPJ,oBAOI,WAAA,eAPJ,qBAOI,WAAA,qBAPJ,mBAOI,WAAA,mBAPJ,sBAOI,WAAA,iBAPJ,wBAOI,WAAA,mBAPJ,uBAOI,WAAA,kBAPJ,gBAOI,MAAA,aAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,eAOI,MAAA,YAPJ,QAOI,OAAA,YAPJ,QAOI,OAAA,iBAPJ,QAOI,OAAA,gBAPJ,QAOI,OAAA,eAPJ,QAOI,OAAA,iBAPJ,QAOI,OAAA,eAPJ,WAOI,OAAA,eAPJ,SAOI,aAAA,YAAA,YAAA,YAPJ,SAOI,aAAA,iBAAA,YAAA,iBAPJ,SAOI,aAAA,gBAAA,YAAA,gBAPJ,SAOI,aAAA,eAAA,YAAA,eAPJ,SAOI,aAAA,iBAAA,YAAA,iBAPJ,SAOI,aAAA,eAAA,YAAA,eAPJ,YAOI,aAAA,eAAA,YAAA,eAPJ,SAOI,WAAA,YAAA,cAAA,YAPJ,SAOI,WAAA,iBAAA,cAAA,iBAPJ,SAOI,WAAA,gBAAA,cAAA,gBAPJ,SAOI,WAAA,eAAA,cAAA,eAPJ,SAOI,WAAA,iBAAA,cAAA,iBAPJ,SAOI,WAAA,eAAA,cAAA,eAPJ,YAOI,WAAA,eAAA,cAAA,eAPJ,SAOI,WAAA,YAPJ,SAOI,WAAA,iBAPJ,SAOI,WAAA,gBAPJ,SAOI,WAAA,eAPJ,SAOI,WAAA,iBAPJ,SAOI,WAAA,eAPJ,YAOI,WAAA,eAPJ,SAOI,aAAA,YAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,gBAPJ,SAOI,aAAA,eAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,eAPJ,YAOI,aAAA,eAPJ,SAOI,cAAA,YAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,gBAPJ,SAOI,cAAA,eAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,eAPJ,YAOI,cAAA,eAPJ,SAOI,YAAA,YAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,gBAPJ,SAOI,YAAA,eAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,eAPJ,YAOI,YAAA,eAPJ,QAOI,QAAA,YAPJ,QAOI,QAAA,iBAPJ,QAOI,QAAA,gBAPJ,QAOI,QAAA,eAPJ,QAOI,QAAA,iBAPJ,QAOI,QAAA,eAPJ,SAOI,cAAA,YAAA,aAAA,YAPJ,SAOI,cAAA,iBAAA,aAAA,iBAPJ,SAOI,cAAA,gBAAA,aAAA,gBAPJ,SAOI,cAAA,eAAA,aAAA,eAPJ,SAOI,cAAA,iBAAA,aAAA,iBAPJ,SAOI,cAAA,eAAA,aAAA,eAPJ,SAOI,YAAA,YAAA,eAAA,YAPJ,SAOI,YAAA,iBAAA,eAAA,iBAPJ,SAOI,YAAA,gBAAA,eAAA,gBAPJ,SAOI,YAAA,eAAA,eAAA,eAPJ,SAOI,YAAA,iBAAA,eAAA,iBAPJ,SAOI,YAAA,eAAA,eAAA,eAPJ,SAOI,YAAA,YAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,gBAPJ,SAOI,YAAA,eAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,eAPJ,SAOI,cAAA,YAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,gBAPJ,SAOI,cAAA,eAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,eAPJ,SAOI,eAAA,YAPJ,SAOI,eAAA,iBAPJ,SAOI,eAAA,gBAPJ,SAOI,eAAA,eAPJ,SAOI,eAAA,iBAPJ,SAOI,eAAA,eAPJ,SAOI,aAAA,YAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,gBAPJ,SAOI,aAAA,eAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,eAPJ,UAOI,IAAA,YAPJ,UAOI,IAAA,iBAPJ,UAOI,IAAA,gBAPJ,UAOI,IAAA,eAPJ,UAOI,IAAA,iBAPJ,UAOI,IAAA,eAPJ,eAOI,WAAA,eAPJ,aAOI,WAAA,gBAPJ,gBAOI,WAAA,kB1DVR,yB0DGI,gBAOI,MAAA,eAPJ,cAOI,MAAA,gBAPJ,eAOI,MAAA,eAPJ,aAOI,QAAA,iBAPJ,mBAOI,QAAA,uBAPJ,YAOI,QAAA,gBAPJ,WAOI,QAAA,eAPJ,YAOI,QAAA,gBAPJ,gBAOI,QAAA,oBAPJ,iBAOI,QAAA,qBAPJ,WAOI,QAAA,eAPJ,kBAOI,QAAA,sBAPJ,WAOI,QAAA,eAPJ,cAOI,KAAA,EAAA,EAAA,eAPJ,aAOI,eAAA,cAPJ,gBAOI,eAAA,iBAPJ,qBAOI,eAAA,sBAPJ,wBAOI,eAAA,yBAPJ,gBAOI,UAAA,YAPJ,gBAOI,UAAA,YAPJ,kBAOI,YAAA,YAPJ,kBAOI,YAAA,YAPJ,cAOI,UAAA,eAPJ,gBAOI,UAAA,iBAPJ,sBAOI,UAAA,uBAPJ,0BAOI,gBAAA,qBAPJ,wBAOI,gBAAA,mBAPJ,2BAOI,gBAAA,iBAPJ,4BAOI,gBAAA,wBAPJ,2BAOI,gBAAA,uBAPJ,2BAOI,gBAAA,uBAPJ,sBAOI,YAAA,qBAPJ,oBAOI,YAAA,mBAPJ,uBAOI,YAAA,iBAPJ,yBAOI,YAAA,mBAPJ,wBAOI,YAAA,kBAPJ,wBAOI,cAAA,qBAPJ,sBAOI,cAAA,mBAPJ,yBAOI,cAAA,iBAPJ,0BAOI,cAAA,wBAPJ,yBAOI,cAAA,uBAPJ,0BAOI,cAAA,kBAPJ,oBAOI,WAAA,eAPJ,qBAOI,WAAA,qBAPJ,mBAOI,WAAA,mBAPJ,sBAOI,WAAA,iBAPJ,wBAOI,WAAA,mBAPJ,uBAOI,WAAA,kBAPJ,gBAOI,MAAA,aAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,eAOI,MAAA,YAPJ,QAOI,OAAA,YAPJ,QAOI,OAAA,iBAPJ,QAOI,OAAA,gBAPJ,QAOI,OAAA,eAPJ,QAOI,OAAA,iBAPJ,QAOI,OAAA,eAPJ,WAOI,OAAA,eAPJ,SAOI,aAAA,YAAA,YAAA,YAPJ,SAOI,aAAA,iBAAA,YAAA,iBAPJ,SAOI,aAAA,gBAAA,YAAA,gBAPJ,SAOI,aAAA,eAAA,YAAA,eAPJ,SAOI,aAAA,iBAAA,YAAA,iBAPJ,SAOI,aAAA,eAAA,YAAA,eAPJ,YAOI,aAAA,eAAA,YAAA,eAPJ,SAOI,WAAA,YAAA,cAAA,YAPJ,SAOI,WAAA,iBAAA,cAAA,iBAPJ,SAOI,WAAA,gBAAA,cAAA,gBAPJ,SAOI,WAAA,eAAA,cAAA,eAPJ,SAOI,WAAA,iBAAA,cAAA,iBAPJ,SAOI,WAAA,eAAA,cAAA,eAPJ,YAOI,WAAA,eAAA,cAAA,eAPJ,SAOI,WAAA,YAPJ,SAOI,WAAA,iBAPJ,SAOI,WAAA,gBAPJ,SAOI,WAAA,eAPJ,SAOI,WAAA,iBAPJ,SAOI,WAAA,eAPJ,YAOI,WAAA,eAPJ,SAOI,aAAA,YAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,gBAPJ,SAOI,aAAA,eAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,eAPJ,YAOI,aAAA,eAPJ,SAOI,cAAA,YAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,gBAPJ,SAOI,cAAA,eAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,eAPJ,YAOI,cAAA,eAPJ,SAOI,YAAA,YAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,gBAPJ,SAOI,YAAA,eAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,eAPJ,YAOI,YAAA,eAPJ,QAOI,QAAA,YAPJ,QAOI,QAAA,iBAPJ,QAOI,QAAA,gBAPJ,QAOI,QAAA,eAPJ,QAOI,QAAA,iBAPJ,QAOI,QAAA,eAPJ,SAOI,cAAA,YAAA,aAAA,YAPJ,SAOI,cAAA,iBAAA,aAAA,iBAPJ,SAOI,cAAA,gBAAA,aAAA,gBAPJ,SAOI,cAAA,eAAA,aAAA,eAPJ,SAOI,cAAA,iBAAA,aAAA,iBAPJ,SAOI,cAAA,eAAA,aAAA,eAPJ,SAOI,YAAA,YAAA,eAAA,YAPJ,SAOI,YAAA,iBAAA,eAAA,iBAPJ,SAOI,YAAA,gBAAA,eAAA,gBAPJ,SAOI,YAAA,eAAA,eAAA,eAPJ,SAOI,YAAA,iBAAA,eAAA,iBAPJ,SAOI,YAAA,eAAA,eAAA,eAPJ,SAOI,YAAA,YAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,gBAPJ,SAOI,YAAA,eAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,eAPJ,SAOI,cAAA,YAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,gBAPJ,SAOI,cAAA,eAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,eAPJ,SAOI,eAAA,YAPJ,SAOI,eAAA,iBAPJ,SAOI,eAAA,gBAPJ,SAOI,eAAA,eAPJ,SAOI,eAAA,iBAPJ,SAOI,eAAA,eAPJ,SAOI,aAAA,YAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,gBAPJ,SAOI,aAAA,eAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,eAPJ,UAOI,IAAA,YAPJ,UAOI,IAAA,iBAPJ,UAOI,IAAA,gBAPJ,UAOI,IAAA,eAPJ,UAOI,IAAA,iBAPJ,UAOI,IAAA,eAPJ,eAOI,WAAA,eAPJ,aAOI,WAAA,gBAPJ,gBAOI,WAAA,kB1DVR,0B0DGI,gBAOI,MAAA,eAPJ,cAOI,MAAA,gBAPJ,eAOI,MAAA,eAPJ,aAOI,QAAA,iBAPJ,mBAOI,QAAA,uBAPJ,YAOI,QAAA,gBAPJ,WAOI,QAAA,eAPJ,YAOI,QAAA,gBAPJ,gBAOI,QAAA,oBAPJ,iBAOI,QAAA,qBAPJ,WAOI,QAAA,eAPJ,kBAOI,QAAA,sBAPJ,WAOI,QAAA,eAPJ,cAOI,KAAA,EAAA,EAAA,eAPJ,aAOI,eAAA,cAPJ,gBAOI,eAAA,iBAPJ,qBAOI,eAAA,sBAPJ,wBAOI,eAAA,yBAPJ,gBAOI,UAAA,YAPJ,gBAOI,UAAA,YAPJ,kBAOI,YAAA,YAPJ,kBAOI,YAAA,YAPJ,cAOI,UAAA,eAPJ,gBAOI,UAAA,iBAPJ,sBAOI,UAAA,uBAPJ,0BAOI,gBAAA,qBAPJ,wBAOI,gBAAA,mBAPJ,2BAOI,gBAAA,iBAPJ,4BAOI,gBAAA,wBAPJ,2BAOI,gBAAA,uBAPJ,2BAOI,gBAAA,uBAPJ,sBAOI,YAAA,qBAPJ,oBAOI,YAAA,mBAPJ,uBAOI,YAAA,iBAPJ,yBAOI,YAAA,mBAPJ,wBAOI,YAAA,kBAPJ,wBAOI,cAAA,qBAPJ,sBAOI,cAAA,mBAPJ,yBAOI,cAAA,iBAPJ,0BAOI,cAAA,wBAPJ,yBAOI,cAAA,uBAPJ,0BAOI,cAAA,kBAPJ,oBAOI,WAAA,eAPJ,qBAOI,WAAA,qBAPJ,mBAOI,WAAA,mBAPJ,sBAOI,WAAA,iBAPJ,wBAOI,WAAA,mBAPJ,uBAOI,WAAA,kBAPJ,gBAOI,MAAA,aAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,YAOI,MAAA,YAPJ,eAOI,MAAA,YAPJ,QAOI,OAAA,YAPJ,QAOI,OAAA,iBAPJ,QAOI,OAAA,gBAPJ,QAOI,OAAA,eAPJ,QAOI,OAAA,iBAPJ,QAOI,OAAA,eAPJ,WAOI,OAAA,eAPJ,SAOI,aAAA,YAAA,YAAA,YAPJ,SAOI,aAAA,iBAAA,YAAA,iBAPJ,SAOI,aAAA,gBAAA,YAAA,gBAPJ,SAOI,aAAA,eAAA,YAAA,eAPJ,SAOI,aAAA,iBAAA,YAAA,iBAPJ,SAOI,aAAA,eAAA,YAAA,eAPJ,YAOI,aAAA,eAAA,YAAA,eAPJ,SAOI,WAAA,YAAA,cAAA,YAPJ,SAOI,WAAA,iBAAA,cAAA,iBAPJ,SAOI,WAAA,gBAAA,cAAA,gBAPJ,SAOI,WAAA,eAAA,cAAA,eAPJ,SAOI,WAAA,iBAAA,cAAA,iBAPJ,SAOI,WAAA,eAAA,cAAA,eAPJ,YAOI,WAAA,eAAA,cAAA,eAPJ,SAOI,WAAA,YAPJ,SAOI,WAAA,iBAPJ,SAOI,WAAA,gBAPJ,SAOI,WAAA,eAPJ,SAOI,WAAA,iBAPJ,SAOI,WAAA,eAPJ,YAOI,WAAA,eAPJ,SAOI,aAAA,YAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,gBAPJ,SAOI,aAAA,eAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,eAPJ,YAOI,aAAA,eAPJ,SAOI,cAAA,YAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,gBAPJ,SAOI,cAAA,eAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,eAPJ,YAOI,cAAA,eAPJ,SAOI,YAAA,YAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,gBAPJ,SAOI,YAAA,eAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,eAPJ,YAOI,YAAA,eAPJ,QAOI,QAAA,YAPJ,QAOI,QAAA,iBAPJ,QAOI,QAAA,gBAPJ,QAOI,QAAA,eAPJ,QAOI,QAAA,iBAPJ,QAOI,QAAA,eAPJ,SAOI,cAAA,YAAA,aAAA,YAPJ,SAOI,cAAA,iBAAA,aAAA,iBAPJ,SAOI,cAAA,gBAAA,aAAA,gBAPJ,SAOI,cAAA,eAAA,aAAA,eAPJ,SAOI,cAAA,iBAAA,aAAA,iBAPJ,SAOI,cAAA,eAAA,aAAA,eAPJ,SAOI,YAAA,YAAA,eAAA,YAPJ,SAOI,YAAA,iBAAA,eAAA,iBAPJ,SAOI,YAAA,gBAAA,eAAA,gBAPJ,SAOI,YAAA,eAAA,eAAA,eAPJ,SAOI,YAAA,iBAAA,eAAA,iBAPJ,SAOI,YAAA,eAAA,eAAA,eAPJ,SAOI,YAAA,YAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,gBAPJ,SAOI,YAAA,eAPJ,SAOI,YAAA,iBAPJ,SAOI,YAAA,eAPJ,SAOI,cAAA,YAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,gBAPJ,SAOI,cAAA,eAPJ,SAOI,cAAA,iBAPJ,SAOI,cAAA,eAPJ,SAOI,eAAA,YAPJ,SAOI,eAAA,iBAPJ,SAOI,eAAA,gBAPJ,SAOI,eAAA,eAPJ,SAOI,eAAA,iBAPJ,SAOI,eAAA,eAPJ,SAOI,aAAA,YAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,gBAPJ,SAOI,aAAA,eAPJ,SAOI,aAAA,iBAPJ,SAOI,aAAA,eAPJ,UAOI,IAAA,YAPJ,UAOI,IAAA,iBAPJ,UAOI,IAAA,gBAPJ,UAOI,IAAA,eAPJ,UAOI,IAAA,iBAPJ,UAOI,IAAA,eAPJ,eAOI,WAAA,eAPJ,aAOI,WAAA,gBAPJ,gBAOI,WAAA,kB1DVR,0B0DGI,iBAOI,MAAA,eAPJ,eAOI,MAAA,gBAPJ,gBAOI,MAAA,eAPJ,cAOI,QAAA,iBAPJ,oBAOI,QAAA,uBAPJ,aAOI,QAAA,gBAPJ,YAOI,QAAA,eAPJ,aAOI,QAAA,gBAPJ,iBAOI,QAAA,oBAPJ,kBAOI,QAAA,qBAPJ,YAOI,QAAA,eAPJ,mBAOI,QAAA,sBAPJ,YAOI,QAAA,eAPJ,eAOI,KAAA,EAAA,EAAA,eAPJ,cAOI,eAAA,cAPJ,iBAOI,eAAA,iBAPJ,sBAOI,eAAA,sBAPJ,yBAOI,eAAA,yBAPJ,iBAOI,UAAA,YAPJ,iBAOI,UAAA,YAPJ,mBAOI,YAAA,YAPJ,mBAOI,YAAA,YAPJ,eAOI,UAAA,eAPJ,iBAOI,UAAA,iBAPJ,uBAOI,UAAA,uBAPJ,2BAOI,gBAAA,qBAPJ,yBAOI,gBAAA,mBAPJ,4BAOI,gBAAA,iBAPJ,6BAOI,gBAAA,wBAPJ,4BAOI,gBAAA,uBAPJ,4BAOI,gBAAA,uBAPJ,uBAOI,YAAA,qBAPJ,qBAOI,YAAA,mBAPJ,wBAOI,YAAA,iBAPJ,0BAOI,YAAA,mBAPJ,yBAOI,YAAA,kBAPJ,yBAOI,cAAA,qBAPJ,uBAOI,cAAA,mBAPJ,0BAOI,cAAA,iBAPJ,2BAOI,cAAA,wBAPJ,0BAOI,cAAA,uBAPJ,2BAOI,cAAA,kBAPJ,qBAOI,WAAA,eAPJ,sBAOI,WAAA,qBAPJ,oBAOI,WAAA,mBAPJ,uBAOI,WAAA,iBAPJ,yBAOI,WAAA,mBAPJ,wBAOI,WAAA,kBAPJ,iBAOI,MAAA,aAPJ,aAOI,MAAA,YAPJ,aAOI,MAAA,YAPJ,aAOI,MAAA,YAPJ,aAOI,MAAA,YAPJ,aAOI,MAAA,YAPJ,aAOI,MAAA,YAPJ,gBAOI,MAAA,YAPJ,SAOI,OAAA,YAPJ,SAOI,OAAA,iBAPJ,SAOI,OAAA,gBAPJ,SAOI,OAAA,eAPJ,SAOI,OAAA,iBAPJ,SAOI,OAAA,eAPJ,YAOI,OAAA,eAPJ,UAOI,aAAA,YAAA,YAAA,YAPJ,UAOI,aAAA,iBAAA,YAAA,iBAPJ,UAOI,aAAA,gBAAA,YAAA,gBAPJ,UAOI,aAAA,eAAA,YAAA,eAPJ,UAOI,aAAA,iBAAA,YAAA,iBAPJ,UAOI,aAAA,eAAA,YAAA,eAPJ,aAOI,aAAA,eAAA,YAAA,eAPJ,UAOI,WAAA,YAAA,cAAA,YAPJ,UAOI,WAAA,iBAAA,cAAA,iBAPJ,UAOI,WAAA,gBAAA,cAAA,gBAPJ,UAOI,WAAA,eAAA,cAAA,eAPJ,UAOI,WAAA,iBAAA,cAAA,iBAPJ,UAOI,WAAA,eAAA,cAAA,eAPJ,aAOI,WAAA,eAAA,cAAA,eAPJ,UAOI,WAAA,YAPJ,UAOI,WAAA,iBAPJ,UAOI,WAAA,gBAPJ,UAOI,WAAA,eAPJ,UAOI,WAAA,iBAPJ,UAOI,WAAA,eAPJ,aAOI,WAAA,eAPJ,UAOI,aAAA,YAPJ,UAOI,aAAA,iBAPJ,UAOI,aAAA,gBAPJ,UAOI,aAAA,eAPJ,UAOI,aAAA,iBAPJ,UAOI,aAAA,eAPJ,aAOI,aAAA,eAPJ,UAOI,cAAA,YAPJ,UAOI,cAAA,iBAPJ,UAOI,cAAA,gBAPJ,UAOI,cAAA,eAPJ,UAOI,cAAA,iBAPJ,UAOI,cAAA,eAPJ,aAOI,cAAA,eAPJ,UAOI,YAAA,YAPJ,UAOI,YAAA,iBAPJ,UAOI,YAAA,gBAPJ,UAOI,YAAA,eAPJ,UAOI,YAAA,iBAPJ,UAOI,YAAA,eAPJ,aAOI,YAAA,eAPJ,SAOI,QAAA,YAPJ,SAOI,QAAA,iBAPJ,SAOI,QAAA,gBAPJ,SAOI,QAAA,eAPJ,SAOI,QAAA,iBAPJ,SAOI,QAAA,eAPJ,UAOI,cAAA,YAAA,aAAA,YAPJ,UAOI,cAAA,iBAAA,aAAA,iBAPJ,UAOI,cAAA,gBAAA,aAAA,gBAPJ,UAOI,cAAA,eAAA,aAAA,eAPJ,UAOI,cAAA,iBAAA,aAAA,iBAPJ,UAOI,cAAA,eAAA,aAAA,eAPJ,UAOI,YAAA,YAAA,eAAA,YAPJ,UAOI,YAAA,iBAAA,eAAA,iBAPJ,UAOI,YAAA,gBAAA,eAAA,gBAPJ,UAOI,YAAA,eAAA,eAAA,eAPJ,UAOI,YAAA,iBAAA,eAAA,iBAPJ,UAOI,YAAA,eAAA,eAAA,eAPJ,UAOI,YAAA,YAPJ,UAOI,YAAA,iBAPJ,UAOI,YAAA,gBAPJ,UAOI,YAAA,eAPJ,UAOI,YAAA,iBAPJ,UAOI,YAAA,eAPJ,UAOI,cAAA,YAPJ,UAOI,cAAA,iBAPJ,UAOI,cAAA,gBAPJ,UAOI,cAAA,eAPJ,UAOI,cAAA,iBAPJ,UAOI,cAAA,eAPJ,UAOI,eAAA,YAPJ,UAOI,eAAA,iBAPJ,UAOI,eAAA,gBAPJ,UAOI,eAAA,eAPJ,UAOI,eAAA,iBAPJ,UAOI,eAAA,eAPJ,UAOI,aAAA,YAPJ,UAOI,aAAA,iBAPJ,UAOI,aAAA,gBAPJ,UAOI,aAAA,eAPJ,UAOI,aAAA,iBAPJ,UAOI,aAAA,eAPJ,WAOI,IAAA,YAPJ,WAOI,IAAA,iBAPJ,WAOI,IAAA,gBAPJ,WAOI,IAAA,eAPJ,WAOI,IAAA,iBAPJ,WAOI,IAAA,eAPJ,gBAOI,WAAA,eAPJ,cAOI,WAAA,gBAPJ,iBAOI,WAAA,kBCtDZ,0BD+CQ,MAOI,UAAA,iBAPJ,MAOI,UAAA,eAPJ,MAOI,UAAA,kBAPJ,MAOI,UAAA,kBCnCZ,aD4BQ,gBAOI,QAAA,iBAPJ,sBAOI,QAAA,uBAPJ,eAOI,QAAA,gBAPJ,cAOI,QAAA,eAPJ,eAOI,QAAA,gBAPJ,mBAOI,QAAA,oBAPJ,oBAOI,QAAA,qBAPJ,cAOI,QAAA,eAPJ,qBAOI,QAAA,sBAPJ,cAOI,QAAA","sourcesContent":["@mixin bsBanner($file) {\n /*!\n * Bootstrap #{$file} v5.2.3 (https://getbootstrap.com/)\n * Copyright 2011-2022 The Bootstrap Authors\n * Copyright 2011-2022 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n}\n\n",":root {\n // Note: Custom variable values only support SassScript inside `#{}`.\n\n // Colors\n //\n // Generate palettes for full colors, grays, and theme colors.\n\n @each $color, $value in $colors {\n --#{$prefix}#{$color}: #{$value};\n }\n\n @each $color, $value in $grays {\n --#{$prefix}gray-#{$color}: #{$value};\n }\n\n @each $color, $value in $theme-colors {\n --#{$prefix}#{$color}: #{$value};\n }\n\n @each $color, $value in $theme-colors-rgb {\n --#{$prefix}#{$color}-rgb: #{$value};\n }\n\n --#{$prefix}white-rgb: #{to-rgb($white)};\n --#{$prefix}black-rgb: #{to-rgb($black)};\n --#{$prefix}body-color-rgb: #{to-rgb($body-color)};\n --#{$prefix}body-bg-rgb: #{to-rgb($body-bg)};\n\n // Fonts\n\n // Note: Use `inspect` for lists so that quoted items keep the quotes.\n // See https://github.com/sass/sass/issues/2383#issuecomment-336349172\n --#{$prefix}font-sans-serif: #{inspect($font-family-sans-serif)};\n --#{$prefix}font-monospace: #{inspect($font-family-monospace)};\n --#{$prefix}gradient: #{$gradient};\n\n // Root and body\n // scss-docs-start root-body-variables\n @if $font-size-root != null {\n --#{$prefix}root-font-size: #{$font-size-root};\n }\n --#{$prefix}body-font-family: #{$font-family-base};\n @include rfs($font-size-base, --#{$prefix}body-font-size);\n --#{$prefix}body-font-weight: #{$font-weight-base};\n --#{$prefix}body-line-height: #{$line-height-base};\n --#{$prefix}body-color: #{$body-color};\n @if $body-text-align != null {\n --#{$prefix}body-text-align: #{$body-text-align};\n }\n --#{$prefix}body-bg: #{$body-bg};\n // scss-docs-end root-body-variables\n\n // scss-docs-start root-border-var\n --#{$prefix}border-width: #{$border-width};\n --#{$prefix}border-style: #{$border-style};\n --#{$prefix}border-color: #{$border-color};\n --#{$prefix}border-color-translucent: #{$border-color-translucent};\n\n --#{$prefix}border-radius: #{$border-radius};\n --#{$prefix}border-radius-sm: #{$border-radius-sm};\n --#{$prefix}border-radius-lg: #{$border-radius-lg};\n --#{$prefix}border-radius-xl: #{$border-radius-xl};\n --#{$prefix}border-radius-2xl: #{$border-radius-2xl};\n --#{$prefix}border-radius-pill: #{$border-radius-pill};\n // scss-docs-end root-border-var\n\n --#{$prefix}link-color: #{$link-color};\n --#{$prefix}link-hover-color: #{$link-hover-color};\n\n --#{$prefix}code-color: #{$code-color};\n\n --#{$prefix}highlight-bg: #{$mark-bg};\n}\n","// stylelint-disable property-blacklist, scss/dollar-variable-default\n\n// SCSS RFS mixin\n//\n// Automated responsive values for font sizes, paddings, margins and much more\n//\n// Licensed under MIT (https://github.com/twbs/rfs/blob/main/LICENSE)\n\n// Configuration\n\n// Base value\n$rfs-base-value: 1.25rem !default;\n$rfs-unit: rem !default;\n\n@if $rfs-unit != rem and $rfs-unit != px {\n @error \"`#{$rfs-unit}` is not a valid unit for $rfs-unit. Use `px` or `rem`.\";\n}\n\n// Breakpoint at where values start decreasing if screen width is smaller\n$rfs-breakpoint: 1200px !default;\n$rfs-breakpoint-unit: px !default;\n\n@if $rfs-breakpoint-unit != px and $rfs-breakpoint-unit != em and $rfs-breakpoint-unit != rem {\n @error \"`#{$rfs-breakpoint-unit}` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`.\";\n}\n\n// Resize values based on screen height and width\n$rfs-two-dimensional: false !default;\n\n// Factor of decrease\n$rfs-factor: 10 !default;\n\n@if type-of($rfs-factor) != number or $rfs-factor <= 1 {\n @error \"`#{$rfs-factor}` is not a valid $rfs-factor, it must be greater than 1.\";\n}\n\n// Mode. Possibilities: \"min-media-query\", \"max-media-query\"\n$rfs-mode: min-media-query !default;\n\n// Generate enable or disable classes. Possibilities: false, \"enable\" or \"disable\"\n$rfs-class: false !default;\n\n// 1 rem = $rfs-rem-value px\n$rfs-rem-value: 16 !default;\n\n// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14\n$rfs-safari-iframe-resize-bug-fix: false !default;\n\n// Disable RFS by setting $enable-rfs to false\n$enable-rfs: true !default;\n\n// Cache $rfs-base-value unit\n$rfs-base-value-unit: unit($rfs-base-value);\n\n@function divide($dividend, $divisor, $precision: 10) {\n $sign: if($dividend > 0 and $divisor > 0 or $dividend < 0 and $divisor < 0, 1, -1);\n $dividend: abs($dividend);\n $divisor: abs($divisor);\n @if $dividend == 0 {\n @return 0;\n }\n @if $divisor == 0 {\n @error \"Cannot divide by 0\";\n }\n $remainder: $dividend;\n $result: 0;\n $factor: 10;\n @while ($remainder > 0 and $precision >= 0) {\n $quotient: 0;\n @while ($remainder >= $divisor) {\n $remainder: $remainder - $divisor;\n $quotient: $quotient + 1;\n }\n $result: $result * 10 + $quotient;\n $factor: $factor * .1;\n $remainder: $remainder * 10;\n $precision: $precision - 1;\n @if ($precision < 0 and $remainder >= $divisor * 5) {\n $result: $result + 1;\n }\n }\n $result: $result * $factor * $sign;\n $dividend-unit: unit($dividend);\n $divisor-unit: unit($divisor);\n $unit-map: (\n \"px\": 1px,\n \"rem\": 1rem,\n \"em\": 1em,\n \"%\": 1%\n );\n @if ($dividend-unit != $divisor-unit and map-has-key($unit-map, $dividend-unit)) {\n $result: $result * map-get($unit-map, $dividend-unit);\n }\n @return $result;\n}\n\n// Remove px-unit from $rfs-base-value for calculations\n@if $rfs-base-value-unit == px {\n $rfs-base-value: divide($rfs-base-value, $rfs-base-value * 0 + 1);\n}\n@else if $rfs-base-value-unit == rem {\n $rfs-base-value: divide($rfs-base-value, divide($rfs-base-value * 0 + 1, $rfs-rem-value));\n}\n\n// Cache $rfs-breakpoint unit to prevent multiple calls\n$rfs-breakpoint-unit-cache: unit($rfs-breakpoint);\n\n// Remove unit from $rfs-breakpoint for calculations\n@if $rfs-breakpoint-unit-cache == px {\n $rfs-breakpoint: divide($rfs-breakpoint, $rfs-breakpoint * 0 + 1);\n}\n@else if $rfs-breakpoint-unit-cache == rem or $rfs-breakpoint-unit-cache == \"em\" {\n $rfs-breakpoint: divide($rfs-breakpoint, divide($rfs-breakpoint * 0 + 1, $rfs-rem-value));\n}\n\n// Calculate the media query value\n$rfs-mq-value: if($rfs-breakpoint-unit == px, #{$rfs-breakpoint}px, #{divide($rfs-breakpoint, $rfs-rem-value)}#{$rfs-breakpoint-unit});\n$rfs-mq-property-width: if($rfs-mode == max-media-query, max-width, min-width);\n$rfs-mq-property-height: if($rfs-mode == max-media-query, max-height, min-height);\n\n// Internal mixin used to determine which media query needs to be used\n@mixin _rfs-media-query {\n @if $rfs-two-dimensional {\n @if $rfs-mode == max-media-query {\n @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}), (#{$rfs-mq-property-height}: #{$rfs-mq-value}) {\n @content;\n }\n }\n @else {\n @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}) and (#{$rfs-mq-property-height}: #{$rfs-mq-value}) {\n @content;\n }\n }\n }\n @else {\n @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}) {\n @content;\n }\n }\n}\n\n// Internal mixin that adds disable classes to the selector if needed.\n@mixin _rfs-rule {\n @if $rfs-class == disable and $rfs-mode == max-media-query {\n // Adding an extra class increases specificity, which prevents the media query to override the property\n &,\n .disable-rfs &,\n &.disable-rfs {\n @content;\n }\n }\n @else if $rfs-class == enable and $rfs-mode == min-media-query {\n .enable-rfs &,\n &.enable-rfs {\n @content;\n }\n }\n @else {\n @content;\n }\n}\n\n// Internal mixin that adds enable classes to the selector if needed.\n@mixin _rfs-media-query-rule {\n\n @if $rfs-class == enable {\n @if $rfs-mode == min-media-query {\n @content;\n }\n\n @include _rfs-media-query {\n .enable-rfs &,\n &.enable-rfs {\n @content;\n }\n }\n }\n @else {\n @if $rfs-class == disable and $rfs-mode == min-media-query {\n .disable-rfs &,\n &.disable-rfs {\n @content;\n }\n }\n @include _rfs-media-query {\n @content;\n }\n }\n}\n\n// Helper function to get the formatted non-responsive value\n@function rfs-value($values) {\n // Convert to list\n $values: if(type-of($values) != list, ($values,), $values);\n\n $val: '';\n\n // Loop over each value and calculate value\n @each $value in $values {\n @if $value == 0 {\n $val: $val + ' 0';\n }\n @else {\n // Cache $value unit\n $unit: if(type-of($value) == \"number\", unit($value), false);\n\n @if $unit == px {\n // Convert to rem if needed\n $val: $val + ' ' + if($rfs-unit == rem, #{divide($value, $value * 0 + $rfs-rem-value)}rem, $value);\n }\n @else if $unit == rem {\n // Convert to px if needed\n $val: $val + ' ' + if($rfs-unit == px, #{divide($value, $value * 0 + 1) * $rfs-rem-value}px, $value);\n }\n @else {\n // If $value isn't a number (like inherit) or $value has a unit (not px or rem, like 1.5em) or $ is 0, just print the value\n $val: $val + ' ' + $value;\n }\n }\n }\n\n // Remove first space\n @return unquote(str-slice($val, 2));\n}\n\n// Helper function to get the responsive value calculated by RFS\n@function rfs-fluid-value($values) {\n // Convert to list\n $values: if(type-of($values) != list, ($values,), $values);\n\n $val: '';\n\n // Loop over each value and calculate value\n @each $value in $values {\n @if $value == 0 {\n $val: $val + ' 0';\n }\n\n @else {\n // Cache $value unit\n $unit: if(type-of($value) == \"number\", unit($value), false);\n\n // If $value isn't a number (like inherit) or $value has a unit (not px or rem, like 1.5em) or $ is 0, just print the value\n @if not $unit or $unit != px and $unit != rem {\n $val: $val + ' ' + $value;\n }\n\n @else {\n // Remove unit from $value for calculations\n $value: divide($value, $value * 0 + if($unit == px, 1, divide(1, $rfs-rem-value)));\n\n // Only add the media query if the value is greater than the minimum value\n @if abs($value) <= $rfs-base-value or not $enable-rfs {\n $val: $val + ' ' + if($rfs-unit == rem, #{divide($value, $rfs-rem-value)}rem, #{$value}px);\n }\n @else {\n // Calculate the minimum value\n $value-min: $rfs-base-value + divide(abs($value) - $rfs-base-value, $rfs-factor);\n\n // Calculate difference between $value and the minimum value\n $value-diff: abs($value) - $value-min;\n\n // Base value formatting\n $min-width: if($rfs-unit == rem, #{divide($value-min, $rfs-rem-value)}rem, #{$value-min}px);\n\n // Use negative value if needed\n $min-width: if($value < 0, -$min-width, $min-width);\n\n // Use `vmin` if two-dimensional is enabled\n $variable-unit: if($rfs-two-dimensional, vmin, vw);\n\n // Calculate the variable width between 0 and $rfs-breakpoint\n $variable-width: #{divide($value-diff * 100, $rfs-breakpoint)}#{$variable-unit};\n\n // Return the calculated value\n $val: $val + ' calc(' + $min-width + if($value < 0, ' - ', ' + ') + $variable-width + ')';\n }\n }\n }\n }\n\n // Remove first space\n @return unquote(str-slice($val, 2));\n}\n\n// RFS mixin\n@mixin rfs($values, $property: font-size) {\n @if $values != null {\n $val: rfs-value($values);\n $fluidVal: rfs-fluid-value($values);\n\n // Do not print the media query if responsive & non-responsive values are the same\n @if $val == $fluidVal {\n #{$property}: $val;\n }\n @else {\n @include _rfs-rule {\n #{$property}: if($rfs-mode == max-media-query, $val, $fluidVal);\n\n // Include safari iframe resize fix if needed\n min-width: if($rfs-safari-iframe-resize-bug-fix, (0 * 1vw), null);\n }\n\n @include _rfs-media-query-rule {\n #{$property}: if($rfs-mode == max-media-query, $fluidVal, $val);\n }\n }\n }\n}\n\n// Shorthand helper mixins\n@mixin font-size($value) {\n @include rfs($value);\n}\n\n@mixin padding($value) {\n @include rfs($value, padding);\n}\n\n@mixin padding-top($value) {\n @include rfs($value, padding-top);\n}\n\n@mixin padding-right($value) {\n @include rfs($value, padding-right);\n}\n\n@mixin padding-bottom($value) {\n @include rfs($value, padding-bottom);\n}\n\n@mixin padding-left($value) {\n @include rfs($value, padding-left);\n}\n\n@mixin margin($value) {\n @include rfs($value, margin);\n}\n\n@mixin margin-top($value) {\n @include rfs($value, margin-top);\n}\n\n@mixin margin-right($value) {\n @include rfs($value, margin-right);\n}\n\n@mixin margin-bottom($value) {\n @include rfs($value, margin-bottom);\n}\n\n@mixin margin-left($value) {\n @include rfs($value, margin-left);\n}\n","// stylelint-disable declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n\n// Root\n//\n// Ability to the value of the root font sizes, affecting the value of `rem`.\n// null by default, thus nothing is generated.\n\n:root {\n @if $font-size-root != null {\n @include font-size(var(--#{$prefix}root-font-size));\n }\n\n @if $enable-smooth-scroll {\n @media (prefers-reduced-motion: no-preference) {\n scroll-behavior: smooth;\n }\n }\n}\n\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Prevent adjustments of font size after orientation changes in iOS.\n// 4. Change the default tap highlight to be completely transparent in iOS.\n\n// scss-docs-start reboot-body-rules\nbody {\n margin: 0; // 1\n font-family: var(--#{$prefix}body-font-family);\n @include font-size(var(--#{$prefix}body-font-size));\n font-weight: var(--#{$prefix}body-font-weight);\n line-height: var(--#{$prefix}body-line-height);\n color: var(--#{$prefix}body-color);\n text-align: var(--#{$prefix}body-text-align);\n background-color: var(--#{$prefix}body-bg); // 2\n -webkit-text-size-adjust: 100%; // 3\n -webkit-tap-highlight-color: rgba($black, 0); // 4\n}\n// scss-docs-end reboot-body-rules\n\n\n// Content grouping\n//\n// 1. Reset Firefox's gray color\n\nhr {\n margin: $hr-margin-y 0;\n color: $hr-color; // 1\n border: 0;\n border-top: $hr-border-width solid $hr-border-color;\n opacity: $hr-opacity;\n}\n\n\n// Typography\n//\n// 1. Remove top margins from headings\n// By default, `

`-`

` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n\n%heading {\n margin-top: 0; // 1\n margin-bottom: $headings-margin-bottom;\n font-family: $headings-font-family;\n font-style: $headings-font-style;\n font-weight: $headings-font-weight;\n line-height: $headings-line-height;\n color: $headings-color;\n}\n\nh1 {\n @extend %heading;\n @include font-size($h1-font-size);\n}\n\nh2 {\n @extend %heading;\n @include font-size($h2-font-size);\n}\n\nh3 {\n @extend %heading;\n @include font-size($h3-font-size);\n}\n\nh4 {\n @extend %heading;\n @include font-size($h4-font-size);\n}\n\nh5 {\n @extend %heading;\n @include font-size($h5-font-size);\n}\n\nh6 {\n @extend %heading;\n @include font-size($h6-font-size);\n}\n\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\n\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n\n// Abbreviations\n//\n// 1. Add the correct text decoration in Chrome, Edge, Opera, and Safari.\n// 2. Add explicit cursor to indicate changed behavior.\n// 3. Prevent the text-decoration to be skipped.\n\nabbr[title] {\n text-decoration: underline dotted; // 1\n cursor: help; // 2\n text-decoration-skip-ink: none; // 3\n}\n\n\n// Address\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\n\n// Lists\n\nol,\nul {\n padding-left: 2rem;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\n// 1. Undo browser default\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // 1\n}\n\n\n// Blockquote\n\nblockquote {\n margin: 0 0 1rem;\n}\n\n\n// Strong\n//\n// Add the correct font weight in Chrome, Edge, and Safari\n\nb,\nstrong {\n font-weight: $font-weight-bolder;\n}\n\n\n// Small\n//\n// Add the correct font size in all browsers\n\nsmall {\n @include font-size($small-font-size);\n}\n\n\n// Mark\n\nmark {\n padding: $mark-padding;\n background-color: var(--#{$prefix}highlight-bg);\n}\n\n\n// Sub and Sup\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n\nsub,\nsup {\n position: relative;\n @include font-size($sub-sup-font-size);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n// Links\n\na {\n color: var(--#{$prefix}link-color);\n text-decoration: $link-decoration;\n\n &:hover {\n color: var(--#{$prefix}link-hover-color);\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n &,\n &:hover {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n// Code\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-code;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\n// 1. Remove browser default top margin\n// 2. Reset browser default of `1em` to use `rem`s\n// 3. Don't allow content to break outside\n\npre {\n display: block;\n margin-top: 0; // 1\n margin-bottom: 1rem; // 2\n overflow: auto; // 3\n @include font-size($code-font-size);\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n @include font-size(inherit);\n color: inherit;\n word-break: normal;\n }\n}\n\ncode {\n @include font-size($code-font-size);\n color: var(--#{$prefix}code-color);\n word-wrap: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n @include font-size($kbd-font-size);\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n\n kbd {\n padding: 0;\n @include font-size(1em);\n font-weight: $nested-kbd-font-weight;\n }\n}\n\n\n// Figures\n//\n// Apply a consistent margin strategy (matches our type styles).\n\nfigure {\n margin: 0 0 1rem;\n}\n\n\n// Images and content\n\nimg,\nsvg {\n vertical-align: middle;\n}\n\n\n// Tables\n//\n// Prevent double borders\n\ntable {\n caption-side: bottom;\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: $table-cell-padding-y;\n padding-bottom: $table-cell-padding-y;\n color: $table-caption-color;\n text-align: left;\n}\n\n// 1. Removes font-weight bold by inheriting\n// 2. Matches default `` alignment by inheriting `text-align`.\n// 3. Fix alignment for Safari\n\nth {\n font-weight: $table-th-font-weight; // 1\n text-align: inherit; // 2\n text-align: -webkit-match-parent; // 3\n}\n\nthead,\ntbody,\ntfoot,\ntr,\ntd,\nth {\n border-color: inherit;\n border-style: solid;\n border-width: 0;\n}\n\n\n// Forms\n//\n// 1. Allow labels to use `margin` for spacing.\n\nlabel {\n display: inline-block; // 1\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n// See https://github.com/twbs/bootstrap/issues/24093\n\nbutton {\n // stylelint-disable-next-line property-disallowed-list\n border-radius: 0;\n}\n\n// Explicitly remove focus outline in Chromium when it shouldn't be\n// visible (e.g. as result of mouse click or touch tap). It already\n// should be doing this automatically, but seems to currently be\n// confused and applies its very visible two-tone outline anyway.\n\nbutton:focus:not(:focus-visible) {\n outline: 0;\n}\n\n// 1. Remove the margin in Firefox and Safari\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // 1\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\n// Remove the inheritance of text transform in Firefox\nbutton,\nselect {\n text-transform: none;\n}\n// Set the cursor for non-` +

+
+ + {% block body %}{% endblock body %} + + + + + + + + + \ No newline at end of file diff --git a/fake_db.py b/fake_db.py new file mode 100644 index 0000000..dd8b80e --- /dev/null +++ b/fake_db.py @@ -0,0 +1,35 @@ +import sqlite3 +from faker import Faker +from datetime import datetime + +fake = Faker() + +# Establish SQLite database connection +conn = sqlite3.connect("database.db") +cursor = conn.cursor() + +# Create table +cursor.execute(''' + CREATE TABLE your_table ( + id INTEGER PRIMARY KEY, + item_name TEXT, + cust_id INTEGER, + cust_name TEXT, + start_date DATE + ); +''') + +# Generate and insert sample data +for _ in range(100): + item_name = fake.word() + cust_id = fake.random_int(min=1, max=1000) + cust_name = fake.name() + start_date = fake.date_this_decade() + cursor.execute(''' + INSERT INTO your_table (item_name, cust_id, cust_name, start_date) + VALUES (?, ?, ?, ?); + ''', (item_name, cust_id, cust_name, start_date)) + +# Commit changes and close connection +conn.commit() +conn.close() diff --git a/iteminventorydasa.py b/iteminventorydasa.py new file mode 100644 index 0000000..72e46e4 --- /dev/null +++ b/iteminventorydasa.py @@ -0,0 +1,189 @@ +#!usr/bin/python +import win32com.client +#from win32com.client import constants +import xml.etree.ElementTree as ET +import itemreportquery as irq + +def QBStock(client_socket=None, filename='', searchitems = {}): + + # Connect to Quickbooks + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA') + #ticket = sessionManager.BeginSession("C:\Quickbooks Bogor\qb test\distrindo bakti wutama.qbw", 0) + #ticket = sessionManager.BeginSession("", 0) + #print("constant:",constants.qbFileOpenDoNotCare) + #print("constant:",constants.qmDontCare) + ticket = sessionManager.BeginSession("", 2 ) + + # Send query and receive response + qbxml_query = """ + + + + + + Contains + TS-I502 + + QuantityOnHand + + + + """ + qbxml_query = """ + + + + + TSHT:TS WOODGRAIN:TS-I502 + TSHT:TS WOODGRAIN:TS-I500 + QuantityOnHand + QuantityOnOrder + QuantityOnSalesOrder + FullName + Name + + + + """ + + qbxml_query1 = """ + + + + + QuantityOnHand + QuantityOnOrder + QuantityOnSalesOrder + FullName + Name + + + + """ + + def createSubElement(ET, parentNode, thisNode, text="", whiteSpace = 0, attrib ={}): + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + ItemInventoryQueryRq = createSubElement(ET, QBXMLMsgsRq, "ItemInventoryQueryRq","\n " ,2,{"metaData":"MetaDataAndResponseData"}) + + # # if you have searchitems then loop here + if searchitems: + #print(searchitems) + for searchitem in searchitems: + searchitem = searchitem.strip('"') + FullName = createSubElement(ET, ItemInventoryQueryRq, "FullName", searchitem,6) + + # # if you have searchitems then loop here + # if searchitems: + # NameFilter = createSubElement(ET, ItemInventoryQueryRq, "NameFilter", "\n ",6) + # MatchCriterion = createSubElement(ET, NameFilter, "MatchCriterion", "Contains", 8) + # for searchitem in searchitems: + # Name = createSubElement(ET, NameFilter, "Name", searchitem, 8) + + #ItemInventoryQueryRq = ET.SubElement(QBXMLMsgsRq, "ItemInventoryQueryRq") + #ItemInventoryQueryRq.set("metaData", "MetaDataAndResponseData") + #ItemInventoryQueryRq.set("metaData", "NoMetaData") + #ItemInventoryQueryRq.tail = "\n " + #ItemInventoryQueryRq.text = "\n " + IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "TimeCreated",6) + IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "TimeModified",6) + IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "QuantityOnHand",6) + IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "FullName",6) + IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "Name",6) + IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "Count",6) + #IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "QuantityOnOrder",6) + IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "QuantityOnSalesOrder",4) + + #mydata = ET.tostring(root, encoding = "unicode", method = "xml") + mydata = ET.tostring(root, encoding = "unicode") + #mydata = ET.tostring(root).decode() + #print (mydata,type(mydata)) + #qbxml_query1 = """\n""" + qbxml_query1 = """\n""" + qbxml_query1 = qbxml_query1 + """""" + qbxml_query1 = qbxml_query1 + "\n" + mydata + #print (qbxml_query, type(qbxml_query)) + print("") + + print(qbxml_query1, type(qbxml_query1)) + + print("") + + response_string = sessionManager.ProcessRequest(ticket, qbxml_query1) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + print (response_string) + + # Parse the response into an Element Tree and peel away the layers of response + #QBXML = xml.etree.ElementTree.fromstring(response_string) + QBXML = ET.fromstring(response_string) + print("") + #print(QBXML) + #QBXMLMsgsRs = QBXML.find('QBXMLMsgsRs') + #InventoryAdjustmentQueryRs = QBXMLMsgsRs.getiterator("InventoryAdjustmentRet") + #ItemInventoryQueryRs = QBXMLMsgsRs.iter("ItemInventoryRet") + ItemInventoryQueryRs = QBXML.iter("ItemInventoryRet") + itemInvDict={} + for ItemInvRet in ItemInventoryQueryRs: + try: + QOH = ItemInvRet.find('QuantityOnHand').text + QOSO = ItemInvRet.find('QuantityOnSalesOrder').text + #txnid = ItemInvRet.find('ListID').text + name = ItemInvRet.find('Name').text + fullName = ItemInvRet.find('FullName').text + itemInvDict[fullName] = [name, int(QOH) - int(QOSO)] + print(itemInvDict[name], name, QOH, QOSO) + except AttributeError: + pass + print(" Attribute err") + except: + print("err") + checkItemReportQuery(itemInvDict) + return itemInvDict + +def checkItemReportQuery(itemInvDict): + DictRs=irq.QBStock(searchitems=itemInvDict) + print ("from IRQ:", DictRs) + for item in DictRs: + + #print(item) + if item in itemInvDict: + print(itemInvDict[item], DictRs[item]) + if itemInvDict[item] != DictRs[item]: + print("item:{} berbeda QOH {} di ItemList dan {} di ItemReport".format(item, itemInvDict[item], DictRs[item])) + itemInvDict[item]= [itemInvDict[item][0], "?{}??{}".format(itemInvDict[item][1], DictRs[item][1])] + else: + itemInvDict[item]= [itemInvDict[item][0], "{}=={}".format(itemInvDict[item][1], DictRs[item][1])] + print("") + +if __name__=="__main__": + print('iteminventorydasa main start') + # itemInvDict=QBStock(searchitems={"ECO:0:ECO-002","ECO:0:ECO-001",}) + itemInvDict=QBStock(searchitems={"taco:g_d:TH-048D","ECO:0:ECO-001","TS-Z2223"}) + name = "TS-Z222" + + for x in itemInvDict: + print (x, itemInvDict[x]) + if name in itemInvDict: + print(itemInvDict[name]) + print(itemInvDict["TS-Z222"]) + print(type(itemInvDict), itemInvDict) + print('iteminventorydasa main END') \ No newline at end of file diff --git a/itemreport.py b/itemreport.py new file mode 100644 index 0000000..765bc03 --- /dev/null +++ b/itemreport.py @@ -0,0 +1,222 @@ +#!usr/bin/python +import win32com.client +#from win32com.client import constants +import xml.etree.ElementTree as ET + +def QBStock(client_socket=None, filename='', searchitems = {}): + + # Connect to Quickbooks + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA') + #ticket = sessionManager.BeginSession("C:\Quickbooks Bogor\qb test\distrindo bakti wutama.qbw", 0) + #ticket = sessionManager.BeginSession("", 0) + #print("constant:",constants.qbFileOpenDoNotCare) + #print("constant:",constants.qmDontCare) + ticket = sessionManager.BeginSession("", 2 ) + + # Send query and receive response + qbxml_query = """ + + + + + + Contains + TS-I502 + + QuantityOnHand + + + + """ + qbxml_query = """ + + + + + TSHT:TS WOODGRAIN:TS-I502 + TSHT:TS WOODGRAIN:TS-I500 + QuantityOnHand + QuantityOnOrder + QuantityOnSalesOrder + FullName + Name + + + + """ + qbxml_query = """ + + + + + InventoryStockStatusByItem + + + + """ + + qbxml_query1 = """ + + + + + QuantityOnHand + QuantityOnOrder + QuantityOnSalesOrder + FullName + Name + + + + """ + + def createSubElement(ET, parentNode, thisNode, text="", whiteSpace = 0, attrib ={}): + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + QBXMLMsgsRq.set("onError", "continueOnError") + #QBXMLMsgsRq.tail = "\n" + #QBXMLMsgsRq.text = "\n " + GeneralSummaryReportQueryRq = createSubElement(ET, QBXMLMsgsRq, "GeneralSummaryReportQueryRq","\n " ) + GeneralSummaryReportType = createSubElement(ET, GeneralSummaryReportQueryRq, "GeneralSummaryReportType", "InventoryStockStatusByItem") + ReportItemFilter = createSubElement(ET, GeneralSummaryReportQueryRq, "ReportItemFilter","\n ") + #FullName = createSubElement(ET, ReportItemFilter, "FullName", "TSHT:TS WOODGRAIN:TS-Z188") + #FullName = createSubElement(ET, ReportItemFilter, "FullName", "TACO:G_D:TH-002G") + #FullName = createSubElement(ET, ReportItemFilter, "FullName", "TACO:AA_B_H:TH-107AA") + #ReportTxnTypeFilter = createSubElement(ET, GeneralSummaryReportQueryRq, "ReportTxnTypeFilter","\n ") + #TxnTypeFilter = createSubElement(ET, ReportTxnTypeFilter, "TxnTypeFilter","All") + + # if you have searchitems then loop here + if searchitems: + #print(searchitems) + for searchitem in searchitems: + FullName = createSubElement(ET, ReportItemFilter, "FullName", searchitem,6) + + # # if you have searchitems then loop here + # if searchitems: + # NameFilter = createSubElement(ET, ItemInventoryQueryRq, "NameFilter", "\n ",6) + # MatchCriterion = createSubElement(ET, NameFilter, "MatchCriterion", "Contains", 8) + # for searchitem in searchitems: + # Name = createSubElement(ET, NameFilter, "Name", searchitem, 8) + + #ItemInventoryQueryRq = ET.SubElement(QBXMLMsgsRq, "ItemInventoryQueryRq") + #ItemInventoryQueryRq.set("metaData", "MetaDataAndResponseData") + #ItemInventoryQueryRq.set("metaData", "NoMetaData") + #ItemInventoryQueryRq.tail = "\n " + #ItemInventoryQueryRq.text = "\n " + + # IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "QuantityOnHand",6) + # IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "FullName",6) + # IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "Name",6) + # IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "Count",6) + + #IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "QuantityOnOrder",6) + + #IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "QuantityOnSalesOrder",4) + + + #mydata = ET.tostring(root, encoding = "unicode", method = "xml") + mydata = ET.tostring(root, encoding = "unicode") + #mydata = ET.tostring(root).decode() + #print (mydata,type(mydata)) + #qbxml_query1 = """\n""" + qbxml_query1 = """\n""" + qbxml_query1 = qbxml_query1 + """""" + qbxml_query1 = qbxml_query1 + "\n" + mydata + print (qbxml_query, type(qbxml_query)) + print("") + + print(qbxml_query1, type(qbxml_query1)) + + #print("") + + response_string = sessionManager.ProcessRequest(ticket, qbxml_query1) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + print (response_string) + + # Parse the response into an Element Tree and peel away the layers of response + #QBXML = xml.etree.ElementTree.fromstring(response_string) + itemInvDict={} + QBXML = ET.fromstring(response_string) + print("") + #print(QBXML) + QBXMLMsgsRs = QBXML.find('QBXMLMsgsRs') + #print(QBXMLMsgsRs.tag, QBXMLMsgsRs) + #InventoryAdjustmentQueryRs = QBXMLMsgsRs.getiterator("InventoryAdjustmentRet") + #ItemInventoryQueryRs = QBXMLMsgsRs.iter("ItemInventoryRet") + GeneralSummaryReportQueryRs = QBXML.findall('GeneralSummaryReportQueryRs') + for child in QBXMLMsgsRs: + print(child.tag, child.attrib['statusMessage']) + itemInvDict[child.attrib['statusSeverity']] = [child.attrib['statusMessage'], child.attrib['statusCode']] + #print(GeneralSummaryReportQueryRs) Cannot use this. Result : None + print("") + DataRow = QBXML.iter("DataRow") + + for ItemInvRet in DataRow: + try: + Rowdata = ItemInvRet.find("RowData") + + fullName = Rowdata.attrib["value"] + ColDatas = ItemInvRet.iter("ColData") + + for ColData in ColDatas: + if ColData.attrib["colID"] == "5": + QOH = ColData.attrib["value"] + elif ColData.attrib["colID"] =="6": + QOSO = ColData.attrib["value"] + elif ColData.attrib["colID"] =="8": + QA = ColData.attrib["value"] + print(fullName, QOH, QOSO, QA, getShortName(fullName)) + itemInvDict[fullName] = [getShortName(fullName), int(QOH) - int(QOSO)] + #print(ItemInvRet.attrib, ItemInvRet.tag, ItemInvRet.text) + + # QOH = ItemInvRet.find('QuantityOnHand').text + # QOSO = ItemInvRet.find('QuantityOnSalesOrder').text + # #txnid = ItemInvRet.find('ListID').text + # name = ItemInvRet.find('Name').text + # fullName = ItemInvRet.find('FullName').text + # itemInvDict[fullName] = [name, int(QOH) - int(QOSO)] + # #print(itemInvDict[name], name, QOH, QOSO) + except AttributeError: + pass + print(" Attribute err") + except: + print("err") + print("") + return itemInvDict + +def getShortName(FullName): + #print(FullName) + return FullName.split(":")[-1] + + +if __name__=="__main1__": + itemInvDict=QBStock() +if __name__=="__main__": + itemInvDict=QBStock(searchitems={"ECO:0:ECO-002","ECO:0:ECO-001",}) + print("SEcond") + #itemInvDict=QBStock(searchitems={"ECO:0:ECO-002","ECO:0:ECO-001","TS-Z2223"}) + name = "TS-Z222" + + for x in itemInvDict: + print (x, itemInvDict[x]) + if name in itemInvDict: + print(itemInvDict[name]) + print(itemInvDict["TS-Z222"]) + \ No newline at end of file diff --git a/itemreportquery.py b/itemreportquery.py new file mode 100644 index 0000000..4083110 --- /dev/null +++ b/itemreportquery.py @@ -0,0 +1,222 @@ +#!usr/bin/python +import win32com.client +#from win32com.client import constants +import xml.etree.ElementTree as ET + +def QBStock(client_socket=None, filename='', searchitems = {}): + + # Connect to Quickbooks + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA') + #ticket = sessionManager.BeginSession("C:\Quickbooks Bogor\qb test\distrindo bakti wutama.qbw", 0) + #ticket = sessionManager.BeginSession("", 0) + #print("constant:",constants.qbFileOpenDoNotCare) + #print("constant:",constants.qmDontCare) + ticket = sessionManager.BeginSession("", 2 ) + + # Send query and receive response + qbxml_query = """ + + + + + + Contains + TS-I502 + + QuantityOnHand + + + + """ + qbxml_query = """ + + + + + TSHT:TS WOODGRAIN:TS-I502 + TSHT:TS WOODGRAIN:TS-I500 + QuantityOnHand + QuantityOnOrder + QuantityOnSalesOrder + FullName + Name + + + + """ + qbxml_query = """ + + + + + InventoryStockStatusByItem + + + + """ + + qbxml_query1 = """ + + + + + QuantityOnHand + QuantityOnOrder + QuantityOnSalesOrder + FullName + Name + + + + """ + + def createSubElement(ET, parentNode, thisNode, text="", whiteSpace = 0, attrib ={}): + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + QBXMLMsgsRq.set("onError", "continueOnError") + #QBXMLMsgsRq.tail = "\n" + #QBXMLMsgsRq.text = "\n " + GeneralSummaryReportQueryRq = createSubElement(ET, QBXMLMsgsRq, "GeneralSummaryReportQueryRq","\n " ) + GeneralSummaryReportType = createSubElement(ET, GeneralSummaryReportQueryRq, "GeneralSummaryReportType", "InventoryStockStatusByItem") + ReportItemFilter = createSubElement(ET, GeneralSummaryReportQueryRq, "ReportItemFilter","\n ") + #FullName = createSubElement(ET, ReportItemFilter, "FullName", "TSHT:TS WOODGRAIN:TS-Z188") + #FullName = createSubElement(ET, ReportItemFilter, "FullName", "TACO:G_D:TH-002G") + #FullName = createSubElement(ET, ReportItemFilter, "FullName", "TACO:AA_B_H:TH-107AA") + #ReportTxnTypeFilter = createSubElement(ET, GeneralSummaryReportQueryRq, "ReportTxnTypeFilter","\n ") + #TxnTypeFilter = createSubElement(ET, ReportTxnTypeFilter, "TxnTypeFilter","All") + + # if you have searchitems then loop here + if searchitems: + print(searchitems) + for searchitem in searchitems: + FullName = createSubElement(ET, ReportItemFilter, "FullName", searchitem,6) + + # # if you have searchitems then loop here + # if searchitems: + # NameFilter = createSubElement(ET, ItemInventoryQueryRq, "NameFilter", "\n ",6) + # MatchCriterion = createSubElement(ET, NameFilter, "MatchCriterion", "Contains", 8) + # for searchitem in searchitems: + # Name = createSubElement(ET, NameFilter, "Name", searchitem, 8) + + #ItemInventoryQueryRq = ET.SubElement(QBXMLMsgsRq, "ItemInventoryQueryRq") + #ItemInventoryQueryRq.set("metaData", "MetaDataAndResponseData") + #ItemInventoryQueryRq.set("metaData", "NoMetaData") + #ItemInventoryQueryRq.tail = "\n " + #ItemInventoryQueryRq.text = "\n " + + # IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "QuantityOnHand",6) + # IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "FullName",6) + # IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "Name",6) + # IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "Count",6) + + #IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "QuantityOnOrder",6) + + #IncludeRetElement = createSubElement(ET, ItemInventoryQueryRq, "IncludeRetElement", "QuantityOnSalesOrder",4) + + + #mydata = ET.tostring(root, encoding = "unicode", method = "xml") + mydata = ET.tostring(root, encoding = "unicode") + #mydata = ET.tostring(root).decode() + #print (mydata,type(mydata)) + #qbxml_query1 = """\n""" + qbxml_query1 = """\n""" + qbxml_query1 = qbxml_query1 + """""" + qbxml_query1 = qbxml_query1 + "\n" + mydata + #print (qbxml_query, type(qbxml_query)) + print("") + + #print(qbxml_query1, type(qbxml_query1)) + + #print("") + + response_string = sessionManager.ProcessRequest(ticket, qbxml_query1) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + #print (response_string) + + # Parse the response into an Element Tree and peel away the layers of response + #QBXML = xml.etree.ElementTree.fromstring(response_string) + itemInvDict={} + QBXML = ET.fromstring(response_string) + print("") + #print(QBXML) + QBXMLMsgsRs = QBXML.find('QBXMLMsgsRs') + #print(QBXMLMsgsRs.tag, QBXMLMsgsRs) + #InventoryAdjustmentQueryRs = QBXMLMsgsRs.getiterator("InventoryAdjustmentRet") + #ItemInventoryQueryRs = QBXMLMsgsRs.iter("ItemInventoryRet") + GeneralSummaryReportQueryRs = QBXML.findall('GeneralSummaryReportQueryRs') + for child in QBXMLMsgsRs: + print("IRQ Modul:",child.tag, child.attrib['statusMessage']) + itemInvDict[child.attrib['statusSeverity']] = [child.attrib['statusMessage'], child.attrib['statusCode']] + #print(GeneralSummaryReportQueryRs) Cannot use this. Result : None + #print("") + DataRow = QBXML.iter("DataRow") + + for ItemInvRet in DataRow: + try: + Rowdata = ItemInvRet.find("RowData") + + fullName = Rowdata.attrib["value"] + ColDatas = ItemInvRet.iter("ColData") + + for ColData in ColDatas: + if ColData.attrib["colID"] == "5": + QOH = ColData.attrib["value"] + elif ColData.attrib["colID"] =="6": + QOSO = ColData.attrib["value"] + elif ColData.attrib["colID"] =="8": + QA = ColData.attrib["value"] + print("IRQ Modul:",fullName, QOH, QOSO, QA, getShortName(fullName)) + itemInvDict[fullName] = [getShortName(fullName), int(QOH) - int(QOSO)] + #print(ItemInvRet.attrib, ItemInvRet.tag, ItemInvRet.text) + + # QOH = ItemInvRet.find('QuantityOnHand').text + # QOSO = ItemInvRet.find('QuantityOnSalesOrder').text + # #txnid = ItemInvRet.find('ListID').text + # name = ItemInvRet.find('Name').text + # fullName = ItemInvRet.find('FullName').text + # itemInvDict[fullName] = [name, int(QOH) - int(QOSO)] + # #print(itemInvDict[name], name, QOH, QOSO) + except AttributeError: + pass + print(" Attribute err") + except: + print("err") + print("") + return itemInvDict + +def getShortName(FullName): + #print(FullName) + return FullName.split(":")[-1] + + +if __name__=="__main1__": + itemInvDict=QBStock() +if __name__=="__main__": + itemInvDict=QBStock(searchitems={"ECO:0:ECO-002","ECO:0:ECO-001",}) + print("SEcond") + #itemInvDict=QBStock(searchitems={"ECO:0:ECO-002","ECO:0:ECO-001","TS-Z2223"}) + name = "TS-Z222" + + for x in itemInvDict: + print (x, itemInvDict[x]) + if name in itemInvDict: + print(itemInvDict[name]) + print(itemInvDict["TS-Z222"]) + \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..42dffb5 --- /dev/null +++ b/main.py @@ -0,0 +1,169 @@ +from fastapi.responses import HTMLResponse +from fastapi.templating import Jinja2Templates +from fastapi import FastAPI, Request, UploadFile, Body + +import json +from iteminventorydasa import QBStock +import datetime +from pyQBstockserverV1 import searchStockQB +from qbgeneralsummaryreport import GeneralSummaryReportQuery as GSRQ +import shutil +from qbpurchaseorderquery import PurchaseOrderQuery +import pdfexcel4DNwithxlrd +from ItemInventoryQuery import ItemInventoryQuery +from SO_to_Inv import readSO +import os + +# app = FastAPI() +app = FastAPI(docs_url="/itemreceipt", redoc_url=None) +templates = Jinja2Templates(directory="templates") + +@app.get('/', response_class=HTMLResponse) +async def hello(request:Request, name:str=None): + return templates.TemplateResponse("hello.html", {"request":request, "name":name}) + # return "Hello Word" + +@app.get('/hello/{name}', response_class=HTMLResponse) +async def hello(request:Request, name:str=None): + return templates.TemplateResponse("hello.html", {"request":request, "name":name}) + +@app.get('/podistri/', response_class=HTMLResponse) +async def hello(request:Request, item_name:str=None, cust_id:str=None, cust_name:str=None, start_date:str=None): + print(request.query_params) + q_dict = {'item_name':item_name, 'cust_id':cust_id, 'cust_name':cust_name, 'start_date':start_date} + if not item_name: + return templates.TemplateResponse("po_index.html", {"request":request, "name":item_name}) + + else: + return templates.TemplateResponse("po_index.html", {"request":request, "name":item_name}) + + + + +@app.get('/renew-iteminventory') +async def renew_iteminventory(): + filename = "ItemInventory\ItemInventory_FromQB.xlsx" + item_inv = ItemInventoryQuery( IncludeRetElement=['FullName', 'DataExtRet'], MaxReturned=None) #MaxReturned=None means get ALL items + QBXML = item_inv.create_QBXML() + status, msg = item_inv.to_excel(filename) + if status: + return {'Info': f"Saved to {filename}.", 'Status':'DONE', 'msg':f"{msg}"} + else: + return {'Info': f"NOT Saved", 'Status':'ERROR', 'msg':msg} + +@app.post("/upload-file/") +async def create_upload_file(uploaded_file: UploadFile): + base_file_location = f"DN_Excel_files" + if uploaded_file.filename.endswith(".xls") and uploaded_file.filename.startswith("TCO-DN"): + folder_yearmonth = uploaded_file.filename.split('-') + if len(folder_yearmonth)>3: + folder_yearmonth = folder_yearmonth[2].strip() + folder_location = f"{base_file_location}/{folder_yearmonth}" + file_location = f"{base_file_location}/{folder_yearmonth}/{uploaded_file.filename}" + if not os.path.exists(folder_location): + print('no folder exist. create one now') + os.makedirs(folder_location) + print(f'Main->{file_location}') + else: + status='Error Filename format' + {"info": f"file '{uploaded_file.filename}' is not in the correct filename pattern. example:'TCO-DNxx-yymm-xxxxx.xls','TCO-DNKR-2308-08888.xls' please upload the correct file", "status": status} + with open(file_location, "wb+") as file_object: + shutil.copyfileobj(uploaded_file.file, file_object) + status, retdict = pdfexcel4DNwithxlrd.read_DN_excel(file_location) + if status == False: + msg = f'Error. Cannot Find Item FullName: {retdict}' + status = 'Error' + return {"info": f"file '{uploaded_file.filename}' saved at '{file_location}'", "status": status, "msg": msg} + ini=PurchaseOrderQuery(DN=retdict) + bol_prepareItemReceiptOk, notinthelist = ini.prepareItemReceipt() + print(f'create_upload_file->added DNQty:{ini.PurchaseOrderList}') + ret = ini.create_itemreceiptadd_QBXML() + # print(ret) + if bol_prepareItemReceiptOk: + ret = ini.connect_to_quickbooks(ret) + # print(ret) + status, status_msg = ini.status_ok(ret) + # print(f"create_upload_file->replyfrom qbxml:{ret}") + if status: + print("OK", status_msg) + status = "OK" + else: + print("ERROR", status_msg) + status = "ERROR" + msg = f"ERROR. replyfromqbxml:{ret}" + msg = f"{status}. replyfrom qbxml:{ret}" + else: + print("create_upload_file->not all DN are added") + msg = f"Error. not all DN are added. \n these items not added in the list :\n{notinthelist}" + status = 'Error' + + 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} + +@app.post('/getopenso') +async def getopenso(request: Request, CustomerName: str = Body(...)): + print("getopenso") + # CustomerName = await request.body() + CustomerName = json.loads(CustomerName) + print(f'CustomerName: {CustomerName}', type(CustomerName)) + FullName = CustomerName['CustomerName'] + print(FullName) + ini=readSO.SalesOrderQuery(FullName= FullName, IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'TxnDate', 'RefNumber', 'IsManuallyClosed', 'IsFullyInvoiced','TotalAmount']) + open_sales_orders = ini.get_open_so() + print(f'return opensalesorder:{open_sales_orders}') + return open_sales_orders + +@app.post('/getopensodetail') +async def getopensodetail(request: Request, open_sales_orders = Body(...)): + # open_sales_orders = await request.body() + print(f'opensalesorders: {open_sales_orders}', type(open_sales_orders)) + open_sales_orders=json.loads(open_sales_orders) + open_sales_orders=open_sales_orders['solist'] + print(f'openSOstr:{open_sales_orders}', type(open_sales_orders)) + open_sales_orders=json.loads(open_sales_orders) + print(f'openSOlist:{open_sales_orders}', type(open_sales_orders)) + ini=readSO.SalesOrderQuery(FullName= 'abadi serpong', IncludeRetElement = ['TxnID', 'TimeCreated', 'TimeModified','TxnNumber', 'CustomerRef', 'TxnDate', 'RefNumber', 'IsManuallyClosed', 'IsFullyInvoiced','TotalAmount']) + open_sales_orders_detail = ini.get_open_sales_order(open_sales_orders) + open_sales_orders_detail = json.dumps(open_sales_orders_detail) + print(f'opensalesordersdetail:{open_sales_orders_detail}', type (open_sales_orders_detail)) + return open_sales_orders_detail + +@app.post('/get_stock') +async def get_stock(request: Request): + getstockdict = await request.body() + print("") + print(f'{datetime.datetime.now()} get_stock start -> {type(getstockdict)}, {getstockdict}') + try: + getstockdict = json.loads(getstockdict) + except: + print('error get_stock()') + return {'message':'error getting stock'} + print(f'get_stock -> {type(getstockdict)}, {getstockdict}') + responseRt = searchStockQB(searchitems=getstockdict) + print(f'{datetime.datetime.now()} get_stock finish -> {type(responseRt)}, {responseRt}') + print("") + return responseRt + +@app.post('/dasa2/get_generalsalesreport') +async def get_generalsalesreport(request: Request): + getdict = await request.body() + print("") + print(f'{datetime.datetime.now()} get_gsr start -> {type(getdict)}, {getdict}') + try: + getdict = json.loads(getdict) + except: + print('error get_gsr()') + return {'message':'error getting GeneralSalesReport'} + print(f'get_gsr 1-> {type(getdict)}, {getdict}') + ReportDateMacro = getdict['ReportDateMacro'] if 'ReportDateMacro' in getdict else None + FromReportDate = getdict['FromReportDate'] if 'FromReportDate' in getdict else None + ToReportDate = getdict['ToReportDate'] if 'ToReportDate' in getdict else None + + responseRt = GSRQ(GeneralSummaryReportType='SalesByCustomerSummary', ReportDateMacro=ReportDateMacro, FromReportDate=FromReportDate, ToReportDate=ToReportDate) + # print(f'get_gsr 2-> {type(responseRt)}, {responseRt}') + datas1=responseRt.get_datarow() + # print(f'get_gsr 3-> {type(datas1)}, {datas1}') + print(f'{datetime.datetime.now()} get_gsr 4 finish -> {type(getdict)}, {getdict}') + print("") + + return datas1[0], responseRt.get_total(), datas1[1] \ No newline at end of file diff --git a/main2.py b/main2.py new file mode 100644 index 0000000..bf39fc2 --- /dev/null +++ b/main2.py @@ -0,0 +1,105 @@ +from fastapi import FastAPI, Request, Depends, Query +from fastapi.templating import Jinja2Templates +import databases +import sqlalchemy +from sqlalchemy.sql import text +from sqlalchemy.sql import select, func # Import select and func from sqlalchemy.sql +from typing import Optional +import datetime + +DATABASE_URL = "sqlite:///database.db" + +database = databases.Database(DATABASE_URL) +metadata = sqlalchemy.MetaData() + +your_table = sqlalchemy.Table( + "your_table", + metadata, + sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True), + sqlalchemy.Column("item_name", sqlalchemy.String), + sqlalchemy.Column("cust_id", sqlalchemy.Integer), + sqlalchemy.Column("cust_name", sqlalchemy.String), + sqlalchemy.Column("start_date", sqlalchemy.Date), +) + +engine = sqlalchemy.create_engine(DATABASE_URL) +metadata.create_all(engine) + +app = FastAPI() + +# Initialize Jinja2 templates +templates = Jinja2Templates(directory="templates") + +@app.on_event("startup") +async def startup_database(): + await database.connect() + +@app.on_event("shutdown") +async def shutdown_database(): + await database.disconnect() + +@app.get("/") +async def home(request: Request): + return templates.TemplateResponse("base.html", {"request": request}) + +@app.get("/search/") +async def search_results( + request: Request, + item_name: Optional[str] = None, + cust_id: Optional[str] = Query(None, alias="cust_id"), + cust_name: Optional[str] = None, + start_date: Optional[str] = None, + end_date: Optional[str] = Query(None, alias="end_date"), + page: int = Query(1, alias="page"), + page_size: int = Query(50, alias="page_size"), +): + # Construct the base query + base_query = select([your_table]) + + if item_name: + base_query = base_query.where(your_table.c.item_name.ilike(f"%{item_name}%")) + if cust_id is not None and cust_id.isdigit(): + base_query = base_query.where(your_table.c.cust_id == int(cust_id)) + if cust_name: + base_query = base_query.where(your_table.c.cust_name.ilike(f"%{cust_name}%")) + + if start_date and end_date: + start_date = datetime.datetime.strptime(start_date, "%Y-%m-%d").date() + end_date = datetime.datetime.strptime(end_date, "%Y-%m-%d").date() + base_query = base_query.where(your_table.c.start_date.between(start_date, end_date)) + elif start_date: + start_date = datetime.datetime.strptime(start_date, "%Y-%m-%d").date() + base_query = base_query.where(your_table.c.start_date == start_date) + + # if start_date: + # base_query = base_query.where(your_table.c.start_date == start_date) + + # Fetch all results into memory + all_results = await database.fetch_all(base_query) + + # Calculate pagination + total_results = len(all_results) + total_pages = (total_results + page_size - 1) // page_size + + # Apply pagination to the in-memory results + offset = (page - 1) * page_size + results = all_results[offset : offset + page_size] + + return templates.TemplateResponse( + "search_results.html", + { + "request": request, + "results": results, + "total_pages": total_pages, + "current_page": page, + "page_size": page_size, + "input_values": { + "item_name": item_name, + "cust_id": cust_id, + "cust_name": cust_name, + "start_date": start_date, + "end_date": end_date, + }, + }, + ) + diff --git a/mousemove.py b/mousemove.py new file mode 100644 index 0000000..597be38 --- /dev/null +++ b/mousemove.py @@ -0,0 +1,8 @@ +import pyautogui +import time +pyautogui.FAILSAFE=False +while True: + pyautogui.moveTo(255,255,4) + time.sleep(5) + pyautogui.moveTo(1000,1000,4) + time.sleep(5) \ No newline at end of file diff --git a/pdfexcel4DNwithxlrd.py b/pdfexcel4DNwithxlrd.py new file mode 100644 index 0000000..8cb35a3 --- /dev/null +++ b/pdfexcel4DNwithxlrd.py @@ -0,0 +1,236 @@ +# Python program to +# access Excel files + +# Import required library +# import xlwings as xw + +import pandas as pd +# from openpyxl import load_workbook +# import openpyxl +import xlrd +import configparser +import os + +config = configparser.ConfigParser() +config.read('ItemReceipt.ini') +item_inventory_path = 'ItemInventory\ItemInventory_FromQB.xlsx' +if 'Section 1' in config: + # print('ada') + if 'Item_inventory_path' in config['Section 1']: + # print(config['Section 1']['Item_inventory_path']) + item_inventory_path = config['Section 1']['item_inventory_path'] +print(f'pdfexcel4DNwithxlrd->item_inventory_path:{item_inventory_path}') +# config['Section 1']['key1'] = 'myval1' #change any key or add new one if not there + +# with open('ItemReceipt.ini', 'w') as configfile: # saving to the configfile +# config.write(configfile) + +def read_DN_excel(filename): + # filename="TCO-DNPG-2307-00752.xls" + # wb = openpyxl.load_workbook(filename, data_only=True) + wb = xlrd.open_workbook(filename) + + print(wb) + print(wb.sheets) + # for sheet in wb.worksheets: + # print(sheet) + + # for sheet in wb.sheets(): + # print(sheet.name, sheet.nrows, sheet.ncols) + # for row in range(0, sheet.nrows): + # header = sheet.row_values(row, start_colx=0, end_colx=None) + # print(header) + + + + # Opening an excel file + # wb = xw.Book('example_001.xlsx') + # wb = xw.Book("TCO-DNPG-2307-00752.xlsx") + # inteminvdf = pd.read_excel('ItemInventory140723.xlsx', index_col="NameFromTaco", usecols=['FullName', 'NameFromTaco']) + # inteminvdf = pd.read_excel('ItemInventory140723.xlsx', usecols=['FullName', 'NameFromTaco']) + # print(os.getcwd(), os.path.join(os.getcwd(), item_inventory_path)) + inteminvdf = pd.read_excel(os.path.join(os.getcwd(), item_inventory_path), usecols=['FullName', 'NameFromTaco']) + + # print(inteminvdf) + # print (inteminvdf.index) + # print(inteminvdf.loc['TS-W981', 'FullName']) + # Viewing available + # sheets in it + # wks = xw.sheets + # print("Available sheets :\n", wks) + # print(type(wks), f'count:{len(wks)}') + # # Selecting a sheet + # ws = wks[0] + + # Selecting a value + # from the selected sheet + # val = ws.range("C1").value + # print("A value in sheet1 :", val) + + # Automatic table + # detection from + # a cell + # automatic = ws.range("a10").expand().value + # print("Automatic Table :", automatic) + + # linescount=wb.sheets[0].range('A' + str(wb.sheets[0].cells.last_cell.row)).end('up').row + # print(linescount) + + data=[] + firstpage=True + boldataline=False + # rawdata=wks[0].range("c1").current_region.value + # print(rawdata) + + # 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:]) + # print(DNRefNum) + TxnDate = wb.sheets()[0].cell(2, 3).value.strip().split(" ")[-1] + Memo = DNRefNum + print(f'pdfexcel4DNwithxlrd.py->DNRefNum:{DNRefNum}, TxnDate:{TxnDate}') + DeliveryNotedict={'DNRefNum':DNRefNum, 'TxnDate':TxnDate, 'Memo': Memo} + wks=wb.sheets() + for sheet in wks: + # rawdata=ws.range("c1").current_region.value + # print(rawdata) + # print() + irow=1 + movetonextpage=False + for idxrow in range(0, sheet.nrows): + row = sheet.row_values(idxrow, start_colx=0, end_colx=None) + # print(row) + + # for row in rawdata: + # print(f'irow={irow}', row) + irow+=1 + # print() + if not None and row[0]=="Item No" : + if firstpage: + # print('firstpage') + data.append(row) + boldataline=True + firstpage=False + # continue + else: + # print('Not firstpage') + # data.append(row) + boldataline=True + firstpage=False + elif not movetonextpage: + # print(boldataline, row) + if boldataline: + if row[0] is not None: + if not None and row[0].startswith('Jenis Barang'): + # print('ada Jenis Barang') + pass + elif row[0].startswith('Sub Total') and not None: + # print('sub total found') + boldataline=False + movetonextpage=True + continue + elif row[3] is not None: + if row[3].startswith('Hormat'): + # print('hormatkami found') + boldataline=False + movetonextpage=True + continue + else: + data.append(row) + else: + data.append(row) + elif row[3] is not None: + if row[3].startswith('Hormat'): + boldataline=False + movetonextpage=True + # continue + else: + data.append(row) + else: + data.append(row) + + # print (f'data: {data}') + + for idx, x in enumerate(data): + if x[0].upper() == "ET-06/A1.": ### Change the source from "ET-06/A1." to "ET-06/A1.BOX_100" and replace the UOM from "BOX_100" to "BOX" + x[0] = "ET-06/A1.BOX_100" + x[2] = x[2].replace("BOX_100", "BOX") + 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) + + print(f'len data={len(data)}') + + + newdata=[] + + templist=[] + for idx, dt in enumerate(data): + if dt[0] != 'Item No': + # print(idx,'not item') + if dt[0] is None: + if dt[1]: + templist[1]+=" " + dt[1] + if dt[3]: + templist.append(dt[3]) + templist[3]=templist[3].split("/")[0].strip() + # templist[3]+=" " + dt[3] + if dt[4]: + templist[4]+=" " + dt[4] + newdata.append(templist) + + templist=[] + else: + uom=dt[2].split(" ")[-1] + # print(uom) + dt.append(uom) + dt[2]=int(dt[2].split(".")[0]) + templist=dt + # print(templist) + + # 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") + # 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['NameFromTaco']=df['Item No'] + # print(df) + # df['FullName'] = inteminvdf.loc[df['Item No'],'FullName'] + df=df.merge(inteminvdf, how="left") + + # 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(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']) + # print(df) + lst = df.to_dict('records') + # print(lst) + DeliveryNotedict['lines']=lst + # print(f'pdfexcel4DNwithxlrd.py->DeliveryNotedict:{DeliveryNotedict}') + return True, DeliveryNotedict + +if __name__=="__main__": + # filename = "DN_Excel_files\TCO-DNPG-2307-00048.xls" + # read_DN_excel(filename) + # filename = "DN_Excel_files\TCO-DNPG-2307-00079.xls" + # 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 diff --git a/pyQBstockserverV1.py b/pyQBstockserverV1.py new file mode 100644 index 0000000..642a874 --- /dev/null +++ b/pyQBstockserverV1.py @@ -0,0 +1,180 @@ +# V2 adding stock Krian +# V3 adding offline stock retrieval (excel and stock Krian) + +from __future__ import print_function +#import xlwings as xw +import time +import json +import datetime +import socket, threading, sys +import pywintypes +#from pdfstock import checkpdfstock +#import pdfstock +import importlib +from iteminventorydasa import QBStock +#from itemreportquery import QBStock +from random import randint + +i=0 +init = {'packinglistfilename' : '', 'bind' : '0.0.0.0', 'port' : 9999} +print('Starting') +try: + + filename = sys.argv[0][:sys.argv[0].find('.py')] + '.ini' + print ("opening {}".format(filename)) + + + + with open(filename) as fp: + for line in fp: + splitline = line.split('=') + if splitline[0] in init: + init[splitline[0]] = splitline[1][:splitline[1].find('#')] +except: + print ("Error Opening {}".format(filename)) + +print ("trying to open {}".format(init['packinglistfilename'])) + + + +def convertfloatnoltoint(stock): + if isinstance(stock, (float, int)): + return int(stock) + elif stock == "Nol": + return 0 + elif stock is None: + return 0 + else: + return 0 + + + + + + + + +def searchStockQB(client_socket=None, filename='', searchitems = {}): + #return searchitems + searchitemsRt = {} + #searchitemsRt['month'] = monthstock + print(f"searchStockQB -> {searchitems} = Received Request: {searchitems}") + itemInvDict = QBStock(searchitems = searchitems) + print(f"searchStockQB -> {searchitems} = Received Request: {itemInvDict}") + for searchitem in searchitems: + print (f"searchStockQB -> searachitem: {searchitem}") + searchitem= searchitem.strip('"') + if searchitem in itemInvDict: + #print (itemInvDict[searchitem][0]) + searchitemsRt[itemInvDict[searchitem][0]] = itemInvDict[searchitem][1] + else: + searchitemsRt[searchitem] = "N/A" + + print (f"searchStockQB -> The Return: {searchitemsRt}") + print ("") + #print(datetime.datetime.now()) + #runningTime = datetime.datetime.now()-stime + #print("Finish in: {}.{} sec".format(runningTime.seconds, runningTime.microseconds)) + + if client_socket != None: + data_string = json.dumps(searchitemsRt) + data_string = data_string.encode() + #client_socket.send(json.dumps(searchitemsRt)) + client_socket.send(data_string) + client_socket.close() + + return searchitemsRt + +if __name__=='__main__': + print(init['bind'], init['port']) + bind_ip = init['bind'] #'0.0.0.0' + bind_port = 9999 #init['port'] #9999 + try: + server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server.bind((bind_ip, bind_port)) + server.listen(5) # max backlog of connections + + print ('Listening on {}:{}'.format(bind_ip, bind_port)) + except Exception as error: + print (error) + sys.exit() + + + +def is_json(myjson): + try: + json_object = json.loads(myjson) + json_object = None + except ValueError as e: + return False + return True + + +def handle_offline_request(client_socket, lists): + try: + buffer = 4096 + data_string=lists + data_string = json.dumps(lists) + size = len(data_string) + sSize = "Size {}".format(size) + sSize = sSize.encode() + print("Size to be send:{}; data_string:{}".format(sSize, size)) + client_socket.send(sSize) + request = client_socket.recv(buffer) + request = request.decode() + #print ('Received:{}'.format(request)) + if request.startswith('Got Size'): + data_string = data_string.encode() + client_socket.sendall(data_string) + request = client_socket.recv(buffer) + request = request.decode() + print ('Received:{}'.format(request)) + if request.startswith('Got All Data'): + sBye = "Bye" + sBye = sBye.encode() + client_socket.send(sBye) + except: + print("handle_offline_request Error") + finally: + client_socket.close + +if __name__ == '__main__': + #xyz={"TH-001aa":"","ECO-016":"","th-002":"","ECO:0:ECO-002":""} + xyz={"ECO:0:ECO-002":"","TIERO:R, WY, SU, CM, DM, TR, TM:TI-X-0095-DM":""} + xyz={'"TIERO:R, WY, SU, CM, DM, TR, TM:TI-X-0095-DM"':''} + print ("searchitems", xyz) + responseRt = searchStockQB(searchitems=xyz) + print(responseRt) + + + while i<2: + i=0 + #sys.exit() to cut not going to start listening + client_sock, address = server.accept() + print("") + print("") + print (datetime.datetime.now(), 'Accepted connection from {}:{}'.format(address[0], address[1])) + request = client_sock.recv(4096) + request = request.decode() + print("request:", type(request), request) + if is_json(request): + print("json:{}".format(request)) + abc = json.loads(request) + print(type(abc), abc) + responseRt = searchStockQB(searchitems=abc) + responseRt = json.dumps(responseRt) + responseRt = responseRt.encode() + client_sock.send(responseRt) + client_sock.close() + elif request.lower() == 'request': + #print ("replied request") + dataoffline = getofflineStock(filename=init['packinglistfilename']) + handle_offline_request(client_sock, dataoffline) + # client_sock.send("hi".encode()) + # client_sock.close() + else: + #print("else") + client_sock.send(b'Bye') + client_sock.close() + print(datetime.datetime.now(), "Connection closed") + diff --git a/qbItemInventoryQuery.py b/qbItemInventoryQuery.py new file mode 100644 index 0000000..18eb320 --- /dev/null +++ b/qbItemInventoryQuery.py @@ -0,0 +1,66 @@ +#!usr/bin/python +import win32com.client +import xml.etree.ElementTree + +# Connect to Quickbooks +sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") +sessionManager.OpenConnection('', 'Test qbXML Request') +ticket = sessionManager.BeginSession("", 2) + +# Send query and receive response +qbxml_query = """ + + + + + + + +""" +qbxml_query1 = """ + + + + + +SalesOrder + + + +""" + +qbxml_query = """ + + + + + ActiveOnly + + FullName + Name + + + + +""" + +response_string = sessionManager.ProcessRequest(ticket, qbxml_query) + +# Disconnect from Quickbooks +sessionManager.EndSession(ticket) # Close the company file +sessionManager.CloseConnection() # Close the connection +print (response_string) +# Parse the response into an Element Tree and peel away the layers of response +QBXML = xml.etree.ElementTree.fromstring(response_string) +print("") +print(QBXML) +QBXMLMsgsRs = QBXML.find('QBXMLMsgsRs') +#ItemInventoryQueryRs = QBXMLMsgsRs.getiterator("ItemInventoryRet") +ItemInventoryQueryRs = QBXMLMsgsRs.iter("ItemInventoryRet") + +for ItemInv in ItemInventoryQueryRs: + # txnid = InvAdjRet.find('TxnID').text + print(ItemInv.find('FullName').text) + # FullName = + #memo = InvAdjRet.find('memo').text + # print(txnid) \ No newline at end of file diff --git a/qbgeneralsummaryreport.py b/qbgeneralsummaryreport.py new file mode 100644 index 0000000..1a93ec1 --- /dev/null +++ b/qbgeneralsummaryreport.py @@ -0,0 +1,253 @@ +import xml.etree.ElementTree as ET +import win32com.client +import xmltodict +import pprint +import datetime +import pandas as pd + +class GeneralSummaryReportQuery: + def __init__(self, **kwargs) -> None: + # print(f'kwargs:{kwargs}') + # print(args) + self.GeneralSummaryReportType = kwargs['GeneralSummaryReportType'] if 'GeneralSummaryReportType' in kwargs else 'SalesByCustomerSummary' + self.ReportPeriod = kwargs['ReportPeriod'] if 'ReportPeriod' in kwargs else None + self.ReportDateMacro = None + if 'ReportDateMacro' in kwargs: + if kwargs['ReportDateMacro'] in ['All', 'Today', 'ThisWeek', 'ThisWeekToDate', 'ThisMonth', 'ThisMonthToDate', 'ThisQuarter', 'ThisQuarterToDate', 'ThisYear', 'ThisYearToDate', 'Yesterday', 'LastWeek', 'LastWeekToDate', 'LastMonth', 'LastMonthToDate', 'LastQuarter', 'LastQuarterToDate', 'LastYear', 'LastYearToDate', 'NextWeek', 'NextFourWeeks', 'NextMonth', 'NextQuarter', 'NextYear']: + self.ReportDateMacro = kwargs['ReportDateMacro'] + self.FromReportDate = self.validate_date(kwargs['FromReportDate']) if 'FromReportDate' in kwargs else None + self.ToReportDate = self.validate_date(kwargs['ToReportDate']) if 'ToReportDate' in kwargs else None + self.ReportEntityFilter = kwargs['ReportEntityFilter'] if 'ReportEntityFilter' in kwargs else None + self.FullName = kwargs['FullName'] if 'FullName' in kwargs else None + # print(self.ReportDateMacro, self.ReportPeriod, self.FromReportDate, self.ToReportDate) + + def create_sub_element(self, ET, parentNode, thisNode, text="\n", whiteSpace = 0, attrib =None): + if type(attrib) is not dict: + attrib = {} + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + def create_QBXML(self): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + GeneralSummaryReportQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "GeneralSummaryReportQueryRq","\n " ) + GeneralSummaryReportType = self.create_sub_element(ET, GeneralSummaryReportQueryRq, 'GeneralSummaryReportType', self.GeneralSummaryReportType) + if self.ReportDateMacro: + GeneralSummaryReportType = self.create_sub_element(ET, GeneralSummaryReportQueryRq, "ReportDateMacro", self.ReportDateMacro) + elif type(self.FromReportDate) is datetime.date or type(self.ToReportDate) is datetime.date: + ReportPeriod = self.create_sub_element(ET, GeneralSummaryReportQueryRq, "ReportPeriod", "\n ",) + if type(self.FromReportDate) is datetime.date: + FromReportDate = self.create_sub_element(ET, ReportPeriod, "FromReportDate", self.FromReportDate.strftime('%Y-%m-%d'),4) + if type(self.ToReportDate) is datetime.date: + ToReportDate = self.create_sub_element(ET, ReportPeriod, "ToReportDate", self.ToReportDate.strftime('%Y-%m-%d')) + + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + + return qbxml_query + + def connect_to_quickbooks(self, qbxml_query): + # Connect to Quickbooks + # sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + # sessionManager.OpenConnection('', 'DASA') + # enumfodnc= win32com.client.Dispatch('QBXMLRP2.RequestProcessor') + # print(enumfodnc) + # print(enumfodnc.qbFileOpenDoNotCare) + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA2') + ticket = sessionManager.BeginSession("z:\\DBW Bogor.qbw", 2) + + # Send query and receive response + response_string = sessionManager.ProcessRequest(ticket, qbxml_query) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + # print (response_string) + return response_string + + def __str__(self, *args) -> str: + # return str(self._get_datarow(self.connect_to_quickbooks(self.create_QBXML()))) + # print("__str__") + return str(self.get_datarow()) + # return "hello" + + + def get_datarow(self, *args): + return self._get_datarow(self.connect_to_quickbooks(self.create_QBXML())) + + def get_dict(self, *args): + return pd.DataFrame(self._get_datarow(self.connect_to_quickbooks(self.create_QBXML()))) + + def get_total(self): + return self._get_total(self.connect_to_quickbooks(self.create_QBXML())) + + def status_ok(self, QBXML): + GSRQRs=QBXML.find('.//GeneralSummaryReportQueryRs') + status_code = GSRQRs.attrib #.get('statusCode') + # print(GSRQRs.attrib) + # print(GSRQRs.attrib['statusCode']) + status=GSRQRs.attrib.get('statusMessage') + + print(f'status={status}') + if 'OK' in status: + return True, status_code + else: + return False, status_code + + def get_coldesc(self, QBXML): + coldescs = QBXML.findall('.//ColDesc') + coldesclist=[] + firstcol=[] + allcols=[] + for idx, coldesc in enumerate(coldescs): + coltitles = coldesc.findall('ColTitle') + # coldesclist.append(coltitles[1].attrib.get('value')) + firstcol.append(coltitles[0].attrib.get('value')) + cols=[] + for idy, coltitle in enumerate(coltitles): + cols.append(coltitle.attrib.get('value')) + # allcols[idy].append(coltitle.attrib.get('value')) + # print(idx, coltitle.tag) + # print(idx, coltitle.attrib.get('value')) + allcols.append(cols) + print(f'getcoldesc:{firstcol}; coldesclist:{coldesclist}; allcols:{allcols}') + # print(allcols) + return allcols + + def _get_total(self, response_string): + # print(response_string) + # Parse the response into an Element Tree and peel away the layers of response + QBXML = ET.fromstring(response_string) + if self.status_ok(QBXML): + print("") + # print(QBXML) + # QBXMLMsgsRs = QBXML.find('QBXMLMsgsRs') #this is a must have. dont CHANGE. this is the root + total = QBXML.findall('.//TotalRow') + return {'Total':total[0][1].attrib.get('value')} + else: + return () + + def get_reportsubtitle(self, QBXML): + reportsubtitle=QBXML.find('.//ReportSubtitle').text + return reportsubtitle + + def _get_datarow(self, response_string): + # print(response_string) + print('get_datarow') + # Parse the response into an Element Tree and peel away the layers of response + QBXML = ET.fromstring(response_string) + datadict={} + reportsubtitle=None + total = float(QBXML.find('.//TotalRow')[1].attrib.get('value')) + status, statusdict= self.status_ok(QBXML) + print(status, statusdict, total) + if status and total > 0: + # print("get_datarow status ok") + reportsubtitle=self.get_reportsubtitle(QBXML) + DataRowRs = QBXML.iter("DataRow") + col_desc=self.get_coldesc(QBXML) + # print(f'getdatarow coldesc:{col_desc}') + # print(f'Datarow length:{len(list(DataRowRs))}') + temp=[] + rowvalue=[] + amount=[] + rowType=[] + idxerrorcount=0 + # print(DataRowRs) + for idx_datarow, DataRow in enumerate(DataRowRs): + # print(DataRow.attrib.get('rowNumber')) + RowData=DataRow.find('RowData') + if RowData is None: + print(f'{idx_datarow} none continue') + idxerrorcount+=1 + continue + if 'value' not in DataRow.find('RowData').attrib: + print(f'{idx_datarow} value continue') + idxerrorcount+=1 + continue + RowData_value=DataRow.find('RowData').attrib.get('value') + rowType.append(RowData_value) + ColDatas = DataRow.findall("ColData") + cols=[] + for idx_coldata, coldata in enumerate(ColDatas): + if idx_coldata==0: + cols.append(rowType[idx_datarow-idxerrorcount]) + else: + cols.append(coldata.attrib.get('value')) + rowvalue.append(cols) + temp.append(ColDatas[0].attrib.get('value')) + # datadict[ColDatas[0].attrib.get('colID')]=temp + amount.append(ColDatas[1].attrib.get('value')) + # datadict[ColDatas[1].attrib.get('colID')]=amount + # print(rowvalue) + datadict['rowvalue']=rowvalue + datadict['RowType']=rowType + datadict['CustomerFullName']=temp #ganti dgn rowType + datadict['Sales']=amount + # print(f"lendatadict {len(datadict['CustomerFullName'])}, {len(datadict['Sales'])}, {len(datadict['RowType'])}, {len(datadict['rowvalue'])}") + + df=pd.DataFrame(rowvalue) + col_desc= [cdesc[-1] for cdesc in col_desc] + print(f'coldesc getdatarow:{col_desc}') + + # print(df) + df.columns=col_desc + # print(df) + # print('lendatadict') + print(f"lendatadict {len(datadict['CustomerFullName'])}, {len(datadict['Sales'])}, {len(datadict['RowType'])}, {len(datadict['rowvalue'])}") + datadict=df.to_dict('list') + # print(datadict, type(datadict)) + return datadict, reportsubtitle + else: + return datadict, reportsubtitle + + def validate_date(self, date_text): + if date_text is None: + return None + try: + return datetime.datetime.strptime(date_text, '%Y-%m-%d').date() + except ValueError: + return None + # raise ValueError("Incorrect data format, should be YYYY-MM-DD") +print('### GeneralSummaryReport ###') +if __name__ == '__main__': + ini=GeneralSummaryReportQuery(ReportDateMacro='LastYear') + # ini=GeneralSummaryReportQuery(FromReportDate='2023-01-11', ToReportDate='2023-01-12') + # ini=GeneralSummaryReportQuery(GeneralSummaryReportType='SalesByItemSummary') + # ini=GeneralSummaryReportQuery(GeneralSummaryReportType='SalesByRepSummary') + # ini=GeneralSummaryReportQuery(GeneralSummaryReportType='PurchaseByVendorSummary') + # ini=GeneralSummaryReportQuery(GeneralSummaryReportType='ProfitAndLossStandard') + # ini=GeneralSummaryReportQuery(GeneralSummaryReportType='PhysicalInventoryWorksheet') + # ini=GeneralSummaryReportQuery(GeneralSummaryReportType='InventoryStockStatusByItem') + print(ini.create_QBXML()) + # print(f'print ini:{ini}') + # print(type(ini.get_datarow())) + # print(ini.get_total()) + # print(f'ini.getdatarow:{ini.get_datarow()}') + df=pd.DataFrame(ini.get_datarow()[0]) + headers=list(df.columns) + print(df.tail(10)) + df.columns=['CustomerFullName', 'TotalSales'] + # df['TotalSales']=df['TotalSales'].astype(float) + df['TotalSales']=pd.to_numeric(df['TotalSales']) + # df['TotalSales']=df['TotalSales'].astype('Int64') + print(df.loc[df['TotalSales']>0]) + print(df.tail(10)) + print(headers) + print(list(df.keys().values)) \ No newline at end of file diff --git a/qbpurchaseorderquery.py b/qbpurchaseorderquery.py new file mode 100644 index 0000000..8c14dc4 --- /dev/null +++ b/qbpurchaseorderquery.py @@ -0,0 +1,387 @@ +import xml.etree.ElementTree as ET +import win32com.client +import xmltodict +import pprint +import datetime +import pandas as pd +from datetime import date +import timeit + +class PurchaseOrderQuery: + def __init__(self, **kwargs) -> None: + # print(f'kwargs:{kwargs}') + # print(args) + # self.PurchaseOrderList=[] + self.DN = kwargs['DN'] if 'DN' in kwargs else {} + self.Reuse = kwargs['Reuse'] if 'Reuse' in kwargs else None + + self.PurchaseOrderList= kwargs['PurchaseOrderList'] if 'PurchaseOrderList' in kwargs else [] + + self.PurchaseOrderType = kwargs['PurchaseOrderType'] if 'PurchaseOrderType' in kwargs else 'SalesByCustomerSummary' + self.IncludeLineItems = kwargs['IncludeLineItems'] if 'IncludeLineItems' in kwargs else 'true' + self.TxnDateRangeFilter = kwargs['TxnDateRangeFilter'] if 'TxnDateRangeFilter' in kwargs else None + self.DateMacro = None + if 'DateMacro' in kwargs: + if kwargs['DateMacro'] in ['All', 'Today', 'ThisWeek', 'ThisWeekToDate', 'ThisMonth', 'ThisMonthToDate', 'ThisQuarter', 'ThisQuarterToDate', 'ThisYear', 'ThisYearToDate', 'Yesterday', 'LastWeek', 'LastWeekToDate', 'LastMonth', 'LastMonthToDate', 'LastQuarter', 'LastQuarterToDate', 'LastYear', 'LastYearToDate', 'NextWeek', 'NextFourWeeks', 'NextMonth', 'NextQuarter', 'NextYear']: + self.DateMacro = kwargs['DateMacro'] + self.FromTxnDate = self.validate_date(kwargs['FromTxnDate']) if 'FromTxnDate' in kwargs else None + self.ToTxnDate = self.validate_date(kwargs['ToTxnDate']) if 'ToTxnDate' in kwargs else None + self.ReportEntityFilter = kwargs['ReportEntityFilter'] if 'ReportEntityFilter' in kwargs else None + self.FullName = kwargs['FullName'] if 'FullName' in kwargs else None + # print(self.DateMacro, self.TxnDateRangeFilter, self.FromTxnDate, self.ToTxnDate) + # 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.get_purchase_order_header() + + def create_sub_element(self, ET, parentNode, thisNode, text="\n", whiteSpace = 0, attrib =None): + if type(attrib) is not dict: + attrib = {} + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + def create_QBXML(self): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + PurchaseOrderQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "PurchaseOrderQueryRq","\n " ) + # PurchaseOrderType = self.create_sub_element(ET, PurchaseOrderQueryRq, 'PurchaseOrderType', self.PurchaseOrderType) + print(f'refnumber:{self.RefNumber}') + if self.RefNumber: + for rn in self.RefNumber: + RefNumber = self.create_sub_element(ET, PurchaseOrderQueryRq, "RefNumber", f'{rn}', 4) + elif self.DateMacro: + TxnDateRangeFilter = self.create_sub_element(ET, PurchaseOrderQueryRq, "TxnDateRangeFilter", "\n ",) + PurchaseOrderType = self.create_sub_element(ET, TxnDateRangeFilter, "DateMacro", self.DateMacro) + # PurchaseOrderType = self.create_sub_element(ET, PurchaseOrderQueryRq, "DateMacro", self.DateMacro) + + elif type(self.FromTxnDate) is datetime.date or type(self.ToTxnDate) is datetime.date: + TxnDateRangeFilter = self.create_sub_element(ET, PurchaseOrderQueryRq, "TxnDateRangeFilter", "\n ",) + if type(self.FromTxnDate) is datetime.date: + FromTxnDate = self.create_sub_element(ET, TxnDateRangeFilter, "FromTxnDate", self.FromTxnDate.strftime('%Y-%m-%d'),4) + if type(self.ToTxnDate) is datetime.date: + ToTxnDate = self.create_sub_element(ET, TxnDateRangeFilter, "ToTxnDate", self.ToTxnDate.strftime('%Y-%m-%d')) + if self.IncludeLineItems: + IncludeLineItems = self.create_sub_element(ET, PurchaseOrderQueryRq, "IncludeLineItems", self.IncludeLineItems, 4) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + print(f'create_QBXML->qbxml_query: {qbxml_query}') + return qbxml_query + + def create_itemreceiptadd_QBXML(self): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + ItemReceiptAddRq = self.create_sub_element(ET, QBXMLMsgsRq, "ItemReceiptAddRq", "\n ",2 ) + ItemReceiptAdd = self.create_sub_element(ET, ItemReceiptAddRq, "ItemReceiptAdd", "\n ",4 ) + VendorRef = self.create_sub_element(ET, ItemReceiptAdd, "VendorRef", "\n ",8 ) + FullName = self.create_sub_element(ET, VendorRef, "FullName", "TACO", 8 ) + today = str(date.today()) + TxnDate = self.create_sub_element(ET, ItemReceiptAdd, "TxnDate", self.DN['TxnDate'], 8 ) + RefNumber = self.create_sub_element(ET, ItemReceiptAdd, "RefNumber", self.DN['DNRefNum'], 8 ) + Memo = self.create_sub_element(ET, ItemReceiptAdd, "Memo", self.DN['Memo'], 10 ) + for purchaseorder in self.PurchaseOrderList: + POTxnId = purchaseorder['TxnID'] + print(f'create_itemreceiptadd_QBXML->POTxnID: {POTxnId}') + for itemline in purchaseorder['PurchaseOrderLineRet']: + if 'DNQuantity' in itemline: + ItemLineAdd = self.create_sub_element(ET, ItemReceiptAdd, "ItemLineAdd", "\n ", 10 ) + Quantity = self.create_sub_element(ET, ItemLineAdd, "Quantity", str(itemline['DNQuantity'] ), 12 ) + UnitOfMeasure = self.create_sub_element(ET, ItemLineAdd, "UnitOfMeasure", str(itemline['UOM']), 12 ) + LinkToTxn = self.create_sub_element(ET, ItemLineAdd, "LinkToTxn", "\n ",10 ) + TxnID = self.create_sub_element(ET, LinkToTxn, "TxnID", POTxnId,14 ) + TxnLineID = self.create_sub_element(ET, LinkToTxn, "TxnLineID", itemline['TxnLineID'],12 ) + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + # print(f'create_itemreceiptadd_QBXML->Create_ItemReceiptadd_QBXML: {qbxml_query}') + # print(f"replyfrom qbxml:{self.connect_to_quickbooks(qbxml_query)}") + + return qbxml_query + + + def connect_to_quickbooks(self, qbxml_query): + # Connect to Quickbooks + # sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + # sessionManager.OpenConnection('', 'DASA') + # enumfodnc= win32com.client.Dispatch('QBXMLRP2.RequestProcessor') + # print(enumfodnc) + # print(enumfodnc.qbFileOpenDoNotCare) + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA2') + # ticket = sessionManager.BeginSession("z:\\DBW Bogor.qbw", 2) + + ticket = sessionManager.BeginSession("", 2) + + # Send query and receive response + response_string = sessionManager.ProcessRequest(ticket, qbxml_query) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + # print (response_string) + return response_string + + def __str__(self, *args) -> str: + # return str(self._get_datarow(self.connect_to_quickbooks(self.create_QBXML()))) + # print("__str__") + return str(self.get_purchase_order_header()) + # return "hello" + + def get_purchase_order_header(self, *args): + return self. _get_purchase_order_header(self.connect_to_quickbooks(self.create_QBXML())) + + def status_ok(self, QBXML): #for ItemReceiptAddRS + + tree = ET.fromstring(QBXML) + + GSRQRs = tree.find(".//ItemReceiptAddRs") + # print(f"GSRQRs:{GSRQRs}") + status_code = GSRQRs.attrib #.get('statusCode') + # print(GSRQRs.attrib) + # print(GSRQRs.attrib['statusCode']) + status=GSRQRs.attrib.get('statusMessage') + + print(f'status={status}') + if 'OK' in status: + return True, status_code + else: + return False, status_code + + + def _get_purchase_order_header(self, response_string): + print('_get_purchase_order_header') + # print(f'responsestring:{response_string}') + QBXML = ET.fromstring(response_string) + datadict = {} + PurchaseOrderdict = {} + _PurchaseOrderlist = [] + PurchaseOrderRets = QBXML.findall('.//PurchaseOrderRet') + for PurchaseOrderRet in PurchaseOrderRets: + RefNumber = PurchaseOrderRet.find('RefNumber').text + Memo = PurchaseOrderRet.find('Memo').text + VendorFullName = PurchaseOrderRet.find('VendorRef/FullName').text + TxnID = PurchaseOrderRet.find('TxnID').text + TotalAmount = PurchaseOrderRet.find('TotalAmount').text + IsFullyReceived = PurchaseOrderRet.find('IsFullyReceived').text + IsManuallyClosed = PurchaseOrderRet.find('IsManuallyClosed').text + # print(VendorFullName, TxnID, TotalAmount) + PurchaseOrderdict = {'RefNumber':RefNumber, 'Memo':Memo, 'VendorFullName':VendorFullName, 'TxnID':TxnID, + 'TotalAmount':TotalAmount, 'IsFullyReceived':IsFullyReceived, 'IsManuallyClosed':IsManuallyClosed, 'PurchaseOrderLineRet':[]} + PurchaseOrderLineRet = PurchaseOrderRet.findall('PurchaseOrderLineRet') + # print(len(PurchaseOrderLineRet)) + if len(PurchaseOrderLineRet) > 0: + for PurchaseOrderLineRet in PurchaseOrderLineRet: + pass + TxnLineID = PurchaseOrderLineRet.find('TxnLineID').text + ItemFullName = PurchaseOrderLineRet.find('ItemRef/FullName').text + Quantity = PurchaseOrderLineRet.find('Quantity').text + UnitOfMeasure = PurchaseOrderLineRet.find('UnitOfMeasure').text + Rate = float(PurchaseOrderLineRet.find('Rate').text) + Amount = float(PurchaseOrderLineRet.find('Amount').text) + ReceivedQuantity = PurchaseOrderLineRet.find('ReceivedQuantity').text + IsBilled = PurchaseOrderLineRet.find('IsBilled').text + LineIsManuallyClosed = PurchaseOrderLineRet.find('IsManuallyClosed').text + # print(TxnLineID, ItemFullName) + BackOrdered = float(Quantity) - float(ReceivedQuantity) + if BackOrdered: + PurchaseOrderLinedict = {'TxnLineID':TxnLineID, + 'ItemFullName':ItemFullName, + 'Quantity':Quantity, + 'UOM':UnitOfMeasure, + 'Rate':Rate, + 'Amount':Amount, + 'BackOrdered':BackOrdered, + 'ReceivedQuantity':ReceivedQuantity, + 'IsBilled':IsBilled, + 'LineIsManuallyClosed':LineIsManuallyClosed, + } + PurchaseOrderdict['PurchaseOrderLineRet'].append(PurchaseOrderLinedict) + _PurchaseOrderlist.append(PurchaseOrderdict) + # print(_PurchaseOrderlist) + self.PurchaseOrderList=_PurchaseOrderlist + # print(f'_get_purchase_order_header->Purchaseorderlist: {self.PurchaseOrderList}') + # return PurchaseOrderlist + + def addDNQtyToPurchaseOrderList(self, _dict:dict): + _bolfoundrefnum=False + _bol_dictisadded=False + Error_msg = None + for poidx, _po in enumerate(self.PurchaseOrderList): + if _po['RefNumber']==_dict['RefNum']: + _bolfoundrefnum=True + if len(_po['PurchaseOrderLineRet'])>0: + bolfind_poline_dict = False + for polineidx, _poline in enumerate(_po['PurchaseOrderLineRet']): + pass + if _poline['ItemFullName']==_dict['FullName']: + bolfind_poline_dict = True + if _poline['UOM'].upper()==_dict['UOM'].upper(): + # first do UOM in _dict convert treatment + QuantityIn_dict = _dict['Quantity'] + if _dict['UOM'].upper().startswith('ROLL_'): + print(f"addDNQtyToPurchaseOrderList->DNqty:{_dict['Quantity']}, Roll_:{_dict['UOM'].split('_')[1]}") + QuantityIn_dict = _dict['Quantity'] * int(_dict['UOM'].split("_")[1]) + pass + elif _dict['UOM'].upper() == 'BOX' and _dict['Item No'].upper() == "CUTTER": + print("addDNQtyToPurchaseOrderList->cutter") + elif _dict['UOM'].upper() == 'BOX' and (_dict['Item No'].upper().startswith("EB-") or _dict['Item No'].upper().startswith("TA-")): + print("addDNQtyToPurchaseOrderList->LEM") + if _dict['Item No'].split("-")[1].endswith("1006"): + QuantityIn_dict = QuantityIn_dict * 12 + elif _dict['Item No'].split("-")[1].endswith("1025"): + QuantityIn_dict = QuantityIn_dict * 6 + elif _dict['Item No'].split("-")[1].endswith("1100"): + pass + print("1100 lem") + elif _dict['UOM'].upper() == 'BOX' and (_dict['Item No'].upper().startswith("TL-") or _dict['Item No'].upper().startswith("TFL-")): + print("addDNQtyToPurchaseOrderList->Lock") + QuantityIn_dict = QuantityIn_dict * 20 + elif _dict['UOM'].upper() == 'BOX' and _dict['Item No'].upper() == "EDG-TRIMMER": + QuantityIn_dict = QuantityIn_dict * 12 #coz box of 12 + + + if _poline['BackOrdered']>=QuantityIn_dict: + self.PurchaseOrderList[poidx]['PurchaseOrderLineRet'][polineidx]['DNQuantity']=float(QuantityIn_dict) + _bol_dictisadded = True + Error_msg= None + break + else: + print(f"{_poline['ItemFullName']} BackOrdered < Qty in DN {_poline['BackOrdered']}<{QuantityIn_dict}") + Error_msg = f"BackOrdered < Qty in DN {_poline['BackOrdered']}<{QuantityIn_dict}" + else: + # print(f"UOM different {_poline['UOM']} <> {_dict['UOM']}") + Error_msg = f"UOM different {_poline['UOM']} <> {_dict['UOM']}" + else: + pass + # print("errorpoline <>DN") + # Error_msg = f"poline[ItemFullName] <> DN[FullName]; {_poline['ItemFullName']} <> {_dict['FullName']}, maybe there are 2 same namefromtaco in QB" + if not bolfind_poline_dict: + Error_msg = f"Cannot find DN:{_dict['FullName']} in poline: {_po['RefNumber']}" + + else: + pass + # print(f"this refnum {_dict['RefNum']} have no QB PO Return Line") + Error_msg = f"this refnum {_dict['RefNum']} have no QB PO Return Line" + + # print (_bol_dictisadded, Error_msg) + return _bol_dictisadded, Error_msg + + + def prepareItemReceipt(self, df:pd.DataFrame = None): + # print(df) + _bolAllDNareOk = True + _notindflist=[] + _yescounter = 0 + _nocounter = 0 + if df is not None: + _dflist = df.to_dict('records') + # print(_dflist) + + else: + _dflist = self.dfDN.to_dict('records') + # print(self.dfDN) + # print(f'_dflist:{_dflist}') + for idx, xdf in enumerate(_dflist): + _boladdDN, _Errormsg = self.addDNQtyToPurchaseOrderList(xdf) + # print(f'prepareItemReceipt->_Errormsg:{_Errormsg}') + if _boladdDN: + _dflist[idx]['ADDED']=True + elif _Errormsg: + _dflist[idx]['ERROR']=_Errormsg + for xdf in (_dflist): + if 'ADDED' not in xdf: + # print (f"prepareItemReceipt->not added: {xdf['Item No']}") + print (f"prepareItemReceipt->not added: {xdf}") + + _notindflist.append(xdf) + _nocounter+=1 + _bolAllDNareOk = False + else: + print (f"ADDED: {xdf['Item No']}") + + print(f'{len(_dflist) - _nocounter} of {len(_dflist)} are added') + return _bolAllDNareOk, _notindflist + + + def validate_date(self, date_text): + if date_text is None: + return None + try: + return datetime.datetime.strptime(date_text, '%Y-%m-%d').date() + except ValueError: + return None + # raise ValueError("Incorrect data format, should be YYYY-MM-DD") + + def get_ext_doc_no_list(self, dndict=None): + if dndict: + dnlist = dndict['lines'] + else: + 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]) + # print(df) + ext_doc_no=df['RefNum'].unique().tolist() + if len(ext_doc_no)>0: + return df, ext_doc_no + else: + return df, None + +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}]} + 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]) + # print(df) + ext_doc_no=df['RefNum'].unique().tolist() + + print(f'isi:{ext_doc_no}') + # ini=PurchaseOrderQuery(DateMacro='ThisWeek', IncludeLineItems='true', RefNumber=["L2307-04429", "L2307-02992", 'L2307-03649',"L2307-02108", "L2307-03638"]) + # ini=PurchaseOrderQuery(DateMacro='ThisWeek', IncludeLineItems='true', RefNumber=["L2307-03638", "L2307-05899"]) + + ini=PurchaseOrderQuery(DateMacro='ThisWeek', IncludeLineItems='true', RefNumber=ext_doc_no, DN=dndict) + # # ini=PurchaseOrderQuery(DateMacro='LastWeek', IncludeLineItems='true') + print(ini.PurchaseOrderList) + bol_prepareItemReceiptOk, notinthelist = ini.prepareItemReceipt(df=df) + print(f'added DNQty:{ini.PurchaseOrderList}') + ret = ini.create_itemreceiptadd_QBXML() + if bol_prepareItemReceiptOk: + # print(f"replyfrom qbxml:{ini.connect_to_quickbooks(ret)}") + print(ret) + status, status_msg = ini.status_ok(ini.connect_to_quickbooks(ret)) + if status: + print("OK", status_msg) + else: + print("ERROR", status_msg) + else: + print("not all DN are added") + + + print("The time difference is :", timeit.default_timer() - starttime) \ No newline at end of file diff --git a/qbquery.py b/qbquery.py new file mode 100644 index 0000000..fedea63 --- /dev/null +++ b/qbquery.py @@ -0,0 +1,63 @@ +#!usr/bin/python +import win32com.client +import xml.etree.ElementTree + +# Connect to Quickbooks +sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") +sessionManager.OpenConnection('', 'Test qbXML Request') +ticket = sessionManager.BeginSession("", 2) + +# Send query and receive response +qbxml_query = """ + + + + + + + +""" +qbxml_query1 = """ + + + + + +SalesOrder + + + +""" + +qbxml_query = """ + + + + + ActiveOnly + + FullName + Name + + + + +""" + +response_string = sessionManager.ProcessRequest(ticket, qbxml_query) + +# Disconnect from Quickbooks +sessionManager.EndSession(ticket) # Close the company file +sessionManager.CloseConnection() # Close the connection +print (response_string) +# Parse the response into an Element Tree and peel away the layers of response +QBXML = xml.etree.ElementTree.fromstring(response_string) +print("") +print(QBXML) +QBXMLMsgsRs = QBXML.find('QBXMLMsgsRs') +#InventoryAdjustmentQueryRs = QBXMLMsgsRs.getiterator("InventoryAdjustmentRet") +InventoryAdjustmentQueryRs = QBXMLMsgsRs.iter("InventoryAdjustmentRet") +for InvAdjRet in InventoryAdjustmentQueryRs: + txnid = InvAdjRet.find('TxnID').text + #memo = InvAdjRet.find('memo').text + # print(txnid) \ No newline at end of file diff --git a/qbsalesorderquery.py b/qbsalesorderquery.py new file mode 100644 index 0000000..0a174fc --- /dev/null +++ b/qbsalesorderquery.py @@ -0,0 +1,253 @@ +import xml.etree.ElementTree as ET +import win32com.client +import xmltodict +import pprint +import datetime +import pandas as pd + +class SalesOrderQuery: + def __init__(self, **kwargs) -> None: + # print(f'kwargs:{kwargs}') + # print(args) + self.SalesOrderType = kwargs['SalesOrderType'] if 'SalesOrderType' in kwargs else 'SalesByCustomerSummary' + self.ReportPeriod = kwargs['ReportPeriod'] if 'ReportPeriod' in kwargs else None + self.ReportDateMacro = None + if 'ReportDateMacro' in kwargs: + if kwargs['ReportDateMacro'] in ['All', 'Today', 'ThisWeek', 'ThisWeekToDate', 'ThisMonth', 'ThisMonthToDate', 'ThisQuarter', 'ThisQuarterToDate', 'ThisYear', 'ThisYearToDate', 'Yesterday', 'LastWeek', 'LastWeekToDate', 'LastMonth', 'LastMonthToDate', 'LastQuarter', 'LastQuarterToDate', 'LastYear', 'LastYearToDate', 'NextWeek', 'NextFourWeeks', 'NextMonth', 'NextQuarter', 'NextYear']: + self.ReportDateMacro = kwargs['ReportDateMacro'] + self.FromReportDate = self.validate_date(kwargs['FromReportDate']) if 'FromReportDate' in kwargs else None + self.ToReportDate = self.validate_date(kwargs['ToReportDate']) if 'ToReportDate' in kwargs else None + self.ReportEntityFilter = kwargs['ReportEntityFilter'] if 'ReportEntityFilter' in kwargs else None + self.FullName = kwargs['FullName'] if 'FullName' in kwargs else None + # print(self.ReportDateMacro, self.ReportPeriod, self.FromReportDate, self.ToReportDate) + + def create_sub_element(self, ET, parentNode, thisNode, text="\n", whiteSpace = 0, attrib =None): + if type(attrib) is not dict: + attrib = {} + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + def create_QBXML(self): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + SalesOrderQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "SalesOrderQueryRq","\n " ) + SalesOrderType = self.create_sub_element(ET, SalesOrderQueryRq, 'SalesOrderType', self.SalesOrderType) + if self.ReportDateMacro: + SalesOrderType = self.create_sub_element(ET, SalesOrderQueryRq, "ReportDateMacro", self.ReportDateMacro) + elif type(self.FromReportDate) is datetime.date or type(self.ToReportDate) is datetime.date: + ReportPeriod = self.create_sub_element(ET, SalesOrderQueryRq, "ReportPeriod", "\n ",) + if type(self.FromReportDate) is datetime.date: + FromReportDate = self.create_sub_element(ET, ReportPeriod, "FromReportDate", self.FromReportDate.strftime('%Y-%m-%d'),4) + if type(self.ToReportDate) is datetime.date: + ToReportDate = self.create_sub_element(ET, ReportPeriod, "ToReportDate", self.ToReportDate.strftime('%Y-%m-%d')) + + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + + return qbxml_query + + def connect_to_quickbooks(self, qbxml_query): + # Connect to Quickbooks + # sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + # sessionManager.OpenConnection('', 'DASA') + # enumfodnc= win32com.client.Dispatch('QBXMLRP2.RequestProcessor') + # print(enumfodnc) + # print(enumfodnc.qbFileOpenDoNotCare) + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA2') + ticket = sessionManager.BeginSession("z:\\DBW Bogor.qbw", 2) + + # Send query and receive response + response_string = sessionManager.ProcessRequest(ticket, qbxml_query) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + # print (response_string) + return response_string + + def __str__(self, *args) -> str: + # return str(self._get_datarow(self.connect_to_quickbooks(self.create_QBXML()))) + # print("__str__") + return str(self.get_datarow()) + # return "hello" + + + def get_datarow(self, *args): + return self._get_datarow(self.connect_to_quickbooks(self.create_QBXML())) + + def get_dict(self, *args): + return pd.DataFrame(self._get_datarow(self.connect_to_quickbooks(self.create_QBXML()))) + + def get_total(self): + return self._get_total(self.connect_to_quickbooks(self.create_QBXML())) + + def status_ok(self, QBXML): + GSRQRs=QBXML.find('.//SalesOrderQueryRs') + status_code = GSRQRs.attrib #.get('statusCode') + # print(GSRQRs.attrib) + # print(GSRQRs.attrib['statusCode']) + status=GSRQRs.attrib.get('statusMessage') + + print(f'status={status}') + if 'OK' in status: + return True, status_code + else: + return False, status_code + + def get_coldesc(self, QBXML): + coldescs = QBXML.findall('.//ColDesc') + coldesclist=[] + firstcol=[] + allcols=[] + for idx, coldesc in enumerate(coldescs): + coltitles = coldesc.findall('ColTitle') + # coldesclist.append(coltitles[1].attrib.get('value')) + firstcol.append(coltitles[0].attrib.get('value')) + cols=[] + for idy, coltitle in enumerate(coltitles): + cols.append(coltitle.attrib.get('value')) + # allcols[idy].append(coltitle.attrib.get('value')) + # print(idx, coltitle.tag) + # print(idx, coltitle.attrib.get('value')) + allcols.append(cols) + print(f'getcoldesc:{firstcol}; coldesclist:{coldesclist}; allcols:{allcols}') + # print(allcols) + return allcols + + def _get_total(self, response_string): + # print(response_string) + # Parse the response into an Element Tree and peel away the layers of response + QBXML = ET.fromstring(response_string) + if self.status_ok(QBXML): + print("") + # print(QBXML) + # QBXMLMsgsRs = QBXML.find('QBXMLMsgsRs') #this is a must have. dont CHANGE. this is the root + total = QBXML.findall('.//TotalRow') + return {'Total':total[0][1].attrib.get('value')} + else: + return () + + def get_reportsubtitle(self, QBXML): + reportsubtitle=QBXML.find('.//ReportSubtitle').text + return reportsubtitle + + def _get_datarow(self, response_string): + # print(response_string) + print('get_datarow') + # Parse the response into an Element Tree and peel away the layers of response + QBXML = ET.fromstring(response_string) + datadict={} + reportsubtitle=None + total = float(QBXML.find('.//TotalRow')[1].attrib.get('value')) + status, statusdict= self.status_ok(QBXML) + print(status, statusdict, total) + if status and total > 0: + # print("get_datarow status ok") + reportsubtitle=self.get_reportsubtitle(QBXML) + DataRowRs = QBXML.iter("DataRow") + col_desc=self.get_coldesc(QBXML) + # print(f'getdatarow coldesc:{col_desc}') + # print(f'Datarow length:{len(list(DataRowRs))}') + temp=[] + rowvalue=[] + amount=[] + rowType=[] + idxerrorcount=0 + # print(DataRowRs) + for idx_datarow, DataRow in enumerate(DataRowRs): + # print(DataRow.attrib.get('rowNumber')) + RowData=DataRow.find('RowData') + if RowData is None: + print(f'{idx_datarow} none continue') + idxerrorcount+=1 + continue + if 'value' not in DataRow.find('RowData').attrib: + print(f'{idx_datarow} value continue') + idxerrorcount+=1 + continue + RowData_value=DataRow.find('RowData').attrib.get('value') + rowType.append(RowData_value) + ColDatas = DataRow.findall("ColData") + cols=[] + for idx_coldata, coldata in enumerate(ColDatas): + if idx_coldata==0: + cols.append(rowType[idx_datarow-idxerrorcount]) + else: + cols.append(coldata.attrib.get('value')) + rowvalue.append(cols) + temp.append(ColDatas[0].attrib.get('value')) + # datadict[ColDatas[0].attrib.get('colID')]=temp + amount.append(ColDatas[1].attrib.get('value')) + # datadict[ColDatas[1].attrib.get('colID')]=amount + # print(rowvalue) + datadict['rowvalue']=rowvalue + datadict['RowType']=rowType + datadict['CustomerFullName']=temp #ganti dgn rowType + datadict['Sales']=amount + # print(f"lendatadict {len(datadict['CustomerFullName'])}, {len(datadict['Sales'])}, {len(datadict['RowType'])}, {len(datadict['rowvalue'])}") + + df=pd.DataFrame(rowvalue) + col_desc= [cdesc[-1] for cdesc in col_desc] + print(f'coldesc getdatarow:{col_desc}') + + # print(df) + df.columns=col_desc + # print(df) + # print('lendatadict') + print(f"lendatadict {len(datadict['CustomerFullName'])}, {len(datadict['Sales'])}, {len(datadict['RowType'])}, {len(datadict['rowvalue'])}") + datadict=df.to_dict('list') + # print(datadict, type(datadict)) + return datadict, reportsubtitle + else: + return datadict, reportsubtitle + + def validate_date(self, date_text): + if date_text is None: + return None + try: + return datetime.datetime.strptime(date_text, '%Y-%m-%d').date() + except ValueError: + return None + # raise ValueError("Incorrect data format, should be YYYY-MM-DD") +print('### SalesOrder ###') +if __name__ == '__main__': + ini=SalesOrderQuery(ReportDateMacro='LastYear') + # ini=SalesOrderQuery(FromReportDate='2023-01-11', ToReportDate='2023-01-12') + # ini=SalesOrderQuery(SalesOrderType='SalesByItemSummary') + # ini=SalesOrderQuery(SalesOrderType='SalesByRepSummary') + # ini=SalesOrderQuery(SalesOrderType='PurchaseByVendorSummary') + # ini=SalesOrderQuery(SalesOrderType='ProfitAndLossStandard') + # ini=SalesOrderQuery(SalesOrderType='PhysicalInventoryWorksheet') + # ini=SalesOrderQuery(SalesOrderType='InventoryStockStatusByItem') + print(ini.create_QBXML()) + print(f'print ini:{ini}') + # print(type(ini.get_datarow())) + # print(ini.get_total()) + # print(f'ini.getdatarow:{ini.get_datarow()}') + df=pd.DataFrame(ini.get_datarow()[0]) + headers=list(df.columns) + print(df.tail(10)) + df.columns=['CustomerFullName', 'TotalSales'] + # df['TotalSales']=df['TotalSales'].astype(float) + df['TotalSales']=pd.to_numeric(df['TotalSales']) + # df['TotalSales']=df['TotalSales'].astype('Int64') + print(df.loc[df['TotalSales']>0]) + print(df.tail(10)) + print(headers) + print(list(df.keys().values)) \ No newline at end of file diff --git a/qbtransactionquery.py b/qbtransactionquery.py new file mode 100644 index 0000000..5ac0cce --- /dev/null +++ b/qbtransactionquery.py @@ -0,0 +1,286 @@ +import xml.etree.ElementTree as ET +import win32com.client +import xmltodict +import pprint +import datetime +import pandas as pd +import xml.dom.minidom +from lxml import etree + +class TransactionQuery: + def __init__(self, **kwargs) -> None: + # print(f'kwargs:{kwargs}') + # print(args) + # self.TransactionTypeFilter = kwargs['TransactionTypeFilter'] if 'TransactionTypeFilter' in kwargs else 'SalesOrder' + self.TxnTypeFilter = kwargs['TxnTypeFilter'] if 'TxnTypeFilter' in kwargs else 'SalesOrder' + # self.TransactionPaidStatusFilter = kwargs['TransactionPaidStatusFilter'] if 'TransactionPaidStatusFilter' in kwargs else 'Open' + self.TransactionPaidStatusFilter = kwargs['TransactionPaidStatusFilter'] if 'TransactionPaidStatusFilter' in kwargs else 'Open' + self.TransactionDetailLevelFilter = kwargs['TransactionDetailLevelFilter'] if 'TransactionDetailLevelFilter' in kwargs else None + self.IncludeRetElement = kwargs['IncludeRetElement'] if 'IncludeRetElement' in kwargs else None + self.IncludeRetElement = self.IncludeRetElement if isinstance(self.IncludeRetElement, list) else None + self.ReportPeriod = kwargs['ReportPeriod'] if 'ReportPeriod' in kwargs else None + self.DateMacro = None + if 'DateMacro' in kwargs: + if kwargs['DateMacro'] in ['All', 'Today', 'ThisWeek', 'ThisWeekToDate', 'ThisMonth', 'ThisMonthToDate', 'ThisQuarter', 'ThisQuarterToDate', 'ThisYear', 'ThisYearToDate', 'Yesterday', 'LastWeek', 'LastWeekToDate', 'LastMonth', 'LastMonthToDate', 'LastQuarter', 'LastQuarterToDate', 'LastYear', 'LastYearToDate', 'NextWeek', 'NextFourWeeks', 'NextMonth', 'NextQuarter', 'NextYear']: + self.DateMacro = kwargs['DateMacro'] + self.FromTxnDate = self.validate_date(kwargs['FromTxnDate']) if 'FromTxnDate' in kwargs else None + self.ToTxnDate = self.validate_date(kwargs['ToTxnDate']) if 'ToTxnDate' in kwargs else None + self.ReportEntityFilter = kwargs['ReportEntityFilter'] if 'ReportEntityFilter' in kwargs else None + self.FullName = kwargs['FullName'] if 'FullName' in kwargs else None + # print(self.DateMacro, self.ReportPeriod, self.FromTxnDate, self.ToTxnDate) + + def create_sub_element(self, ET, parentNode, thisNode, text="\n", whiteSpace = 0, attrib =None): + if type(attrib) is not dict: + attrib = {} + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + def create_QBXML(self): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n" + # root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + # TransactionQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "TransactionQueryRq","\n", attrib={"metaData":"MetaDataAndResponseData", "iteratorID":"UUIDTYPE" }) + TransactionQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "TransactionQueryRq","\n") + if self.DateMacro: + TransactionDateRangeFilter = self.create_sub_element(ET, TransactionQueryRq, "TransactionDateRangeFilter","\n") + # ReportPeriod = self.create_sub_element(ET, TransactionQueryRq, "TransactionDateRangeFilter", "\n ",) + DateMacro = self.create_sub_element(ET, TransactionDateRangeFilter, "DateMacro", self.DateMacro) + elif type(self.FromTxnDate) is datetime.date or type(self.ToTxnDate) is datetime.date: + TransactionDateRangeFilter = self.create_sub_element(ET, TransactionQueryRq, "TransactionDateRangeFilter", "\n",) + # ReportPeriod = self.create_sub_element(ET, TransactionQueryRq, "TransactionDateRangeFilter", "\n ",) + if type(self.FromTxnDate) is datetime.date: + FromTxnDate = self.create_sub_element(ET, TransactionDateRangeFilter, "FromTxnDate", self.FromTxnDate.strftime('%Y-%m-%d')) + if type(self.ToTxnDate) is datetime.date: + ToTxnDate = self.create_sub_element(ET, TransactionDateRangeFilter, "ToTxnDate", self.ToTxnDate.strftime('%Y-%m-%d')) + + + # TransactionQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "TransactionQueryRq","\n " ) + if self.TxnTypeFilter: + TransactionTypeFilter = self.create_sub_element(ET, TransactionQueryRq, 'TransactionTypeFilter', "\n") + TxnTypeFilter = self.create_sub_element(ET, TransactionTypeFilter, "TxnTypeFilter", self.TxnTypeFilter) + if self.TransactionDetailLevelFilter: + TransactionDetailLevelFilter = self.create_sub_element(ET, TransactionQueryRq, 'TransactionDetailLevelFilter', self.TransactionDetailLevelFilter) + TransactionPaidStatusFilter = self.create_sub_element(ET, TransactionQueryRq, 'TransactionPaidStatusFilter', self.TransactionPaidStatusFilter) + if self.IncludeRetElement: + for ire in self.IncludeRetElement: + IncludeRetElement = self.create_sub_element(ET, TransactionQueryRq, 'IncludeRetElement', ire) + mydata = ET.tostring(root, encoding="unicode") + # mydata = ET.tostring(root, encoding = "unicode") + print(mydata) + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + # def to_string(): + # qbxml_query=str(qbxml_query) + return qbxml_query + + def connect_to_quickbooks(self, qbxml_query): + # Connect to Quickbooks + # sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + # sessionManager.OpenConnection('', 'DASA') + # enumfodnc= win32com.client.Dispatch('QBXMLRP2.RequestProcessor') + # print(enumfodnc) + # print(enumfodnc.qbFileOpenDoNotCare) + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA2') + ticket = sessionManager.BeginSession("z:\\DBW Bogor.qbw", 2) + + # Send query and receive response + response_string = sessionManager.ProcessRequest(ticket, qbxml_query) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + # print (response_string) + return response_string + + def __str__(self, *args) -> str: + # return str(self._get_datarow(self.connect_to_quickbooks(self.create_QBXML()))) + # print("__str__") + return str(self.get_datarow()) + # return "hello" + + + def get_datarow(self, *args): + return self._get_datarow(self.connect_to_quickbooks(self.create_QBXML())) + + def get_dict(self, *args): + return pd.DataFrame(self._get_datarow(self.connect_to_quickbooks(self.create_QBXML()))) + + def get_total(self): + return self._get_total(self.connect_to_quickbooks(self.create_QBXML())) + + def status_ok(self, QBXML): + GSRQRs=QBXML.find('.//TransactionQueryRs') + status_code = GSRQRs.attrib #.get('statusCode') + # print(GSRQRs.attrib) + # print(GSRQRs.attrib['statusCode']) + status=GSRQRs.attrib.get('statusMessage') + + print(f'status={status}') + if 'OK' in status: + return True, status_code + else: + return False, status_code + + def get_coldesc(self, QBXML): + coldescs = QBXML.findall('.//ColDesc') + coldesclist=[] + firstcol=[] + allcols=[] + for idx, coldesc in enumerate(coldescs): + coltitles = coldesc.findall('ColTitle') + # coldesclist.append(coltitles[1].attrib.get('value')) + firstcol.append(coltitles[0].attrib.get('value')) + cols=[] + for idy, coltitle in enumerate(coltitles): + cols.append(coltitle.attrib.get('value')) + # allcols[idy].append(coltitle.attrib.get('value')) + # print(idx, coltitle.tag) + # print(idx, coltitle.attrib.get('value')) + allcols.append(cols) + print(f'getcoldesc:{firstcol}; coldesclist:{coldesclist}; allcols:{allcols}') + # print(allcols) + return allcols + + def _get_total(self, response_string): + # print(response_string) + # Parse the response into an Element Tree and peel away the layers of response + QBXML = ET.fromstring(response_string) + if self.status_ok(QBXML): + print("") + # print(QBXML) + # QBXMLMsgsRs = QBXML.find('QBXMLMsgsRs') #this is a must have. dont CHANGE. this is the root + total = QBXML.findall('.//TotalRow') + return {'Total':total[0][1].attrib.get('value')} + else: + return () + + def get_reportsubtitle(self, QBXML): + reportsubtitle=QBXML.find('.//ReportSubtitle').text + return reportsubtitle + + def _get_datarow(self, response_string): + print(response_string) + print('get_datarow') + # Parse the response into an Element Tree and peel away the layers of response + QBXML = ET.fromstring(response_string) + datadict={} + reportsubtitle=None + total = float(QBXML.find('.//TotalRow')[1].attrib.get('value')) + status, statusdict= self.status_ok(QBXML) + print(status, statusdict, total) + if status and total > 0: + # print("get_datarow status ok") + reportsubtitle=self.get_reportsubtitle(QBXML) + DataRowRs = QBXML.iter("DataRow") + col_desc=self.get_coldesc(QBXML) + # print(f'getdatarow coldesc:{col_desc}') + # print(f'Datarow length:{len(list(DataRowRs))}') + temp=[] + rowvalue=[] + amount=[] + rowType=[] + idxerrorcount=0 + # print(DataRowRs) + for idx_datarow, DataRow in enumerate(DataRowRs): + # print(DataRow.attrib.get('rowNumber')) + RowData=DataRow.find('RowData') + if RowData is None: + print(f'{idx_datarow} none continue') + idxerrorcount+=1 + continue + if 'value' not in DataRow.find('RowData').attrib: + print(f'{idx_datarow} value continue') + idxerrorcount+=1 + continue + RowData_value=DataRow.find('RowData').attrib.get('value') + rowType.append(RowData_value) + ColDatas = DataRow.findall("ColData") + cols=[] + for idx_coldata, coldata in enumerate(ColDatas): + if idx_coldata==0: + cols.append(rowType[idx_datarow-idxerrorcount]) + else: + cols.append(coldata.attrib.get('value')) + rowvalue.append(cols) + temp.append(ColDatas[0].attrib.get('value')) + # datadict[ColDatas[0].attrib.get('colID')]=temp + amount.append(ColDatas[1].attrib.get('value')) + # datadict[ColDatas[1].attrib.get('colID')]=amount + # print(rowvalue) + datadict['rowvalue']=rowvalue + datadict['RowType']=rowType + datadict['CustomerFullName']=temp #ganti dgn rowType + datadict['Sales']=amount + # print(f"lendatadict {len(datadict['CustomerFullName'])}, {len(datadict['Sales'])}, {len(datadict['RowType'])}, {len(datadict['rowvalue'])}") + + df=pd.DataFrame(rowvalue) + col_desc= [cdesc[-1] for cdesc in col_desc] + print(f'coldesc getdatarow:{col_desc}') + + # print(df) + df.columns=col_desc + # print(df) + # print('lendatadict') + print(f"lendatadict {len(datadict['CustomerFullName'])}, {len(datadict['Sales'])}, {len(datadict['RowType'])}, {len(datadict['rowvalue'])}") + datadict=df.to_dict('list') + # print(datadict, type(datadict)) + return datadict, reportsubtitle + else: + return datadict, reportsubtitle + + def validate_date(self, date_text): + if date_text is None: + return None + try: + return datetime.datetime.strptime(date_text, '%Y-%m-%d').date() + except ValueError: + return None + # raise ValueError("Incorrect data format, should be YYYY-MM-DD") +print('### Transaction ###') +if __name__ == '__main__': + # ini=TransactionQuery(DateMacro='ThisMonth') + # ini=TransactionQuery() + # temp = xml.dom.minidom.parseString(ini.create_QBXML()) + # print(temp.toprettyxml()) + + # ini=TransactionQuery(FromTxnDate='2023-01-11', ToTxnDate='2023-01-12', TransactionPaidStatusFilter='Closed', TransactionDetailLevelFilter='All') + ini=TransactionQuery(FromTxnDate='2023-01-11', ToTxnDate='2023-01-12', TransactionPaidStatusFilter='Closed', TransactionDetailLevelFilter=None, + IncludeRetElement=['EntityRef', 'TxnDate', 'Amount', 'Memo']) + # ini=TransactionQuery(TransactionTypeFilter='SalesByItemSummary') + # ini=TransactionQuery(TransactionTypeFilter='SalesByRepSummary') + # ini=TransactionQuery(TransactionTypeFilter='PurchaseByVendorSummary') + # ini=TransactionQuery(TransactionTypeFilter='ProfitAndLossStandard') + # ini=TransactionQuery(TransactionTypeFilter='PhysicalInventoryWorksheet') + # ini=TransactionQuery(TransactionTypeFilter='InventoryStockStatusByItem') + print(type(ini.create_QBXML())) + print(ini.create_QBXML()) + print(f'print ini:{ini}') + # print(type(ini.get_datarow())) + # print(ini.get_total()) + # print(f'ini.getdatarow:{ini.get_datarow()}') + + # df=pd.DataFrame(ini.get_datarow()[0]) + # headers=list(df.columns) + # print(df.tail(10)) + # df.columns=['CustomerFullName', 'TotalSales'] + # # df['TotalSales']=df['TotalSales'].astype(float) + # df['TotalSales']=pd.to_numeric(df['TotalSales']) + # # df['TotalSales']=df['TotalSales'].astype('Int64') + # print(df.loc[df['TotalSales']>0]) + # print(df.tail(10)) + # print(headers) + # print(list(df.keys().values)) \ No newline at end of file diff --git a/qbunitofmeasure.py b/qbunitofmeasure.py new file mode 100644 index 0000000..065e586 --- /dev/null +++ b/qbunitofmeasure.py @@ -0,0 +1,111 @@ +import xml.etree.ElementTree as ET +import win32com.client +import xmltodict +import pprint +import datetime +import pandas as pd +from datetime import date +import timeit + +class UnitOfMeasureSetQuery: + def __init__(self, **kwargs) -> None: + # print(f'kwargs:{kwargs}') + # print(args) + # self.PurchaseOrderList=[] + self.PurchaseOrderList= kwargs['PurchaseOrderList'] if 'PurchaseOrderList' in kwargs else [] + self.RefNumber = kwargs['RefNumber'] if 'RefNumber' in kwargs else None + self.PurchaseOrderType = kwargs['PurchaseOrderType'] if 'PurchaseOrderType' in kwargs else 'SalesByCustomerSummary' + self.IncludeLineItems = kwargs['IncludeLineItems'] if 'IncludeLineItems' in kwargs else 'False' + self.TxnDateRangeFilter = kwargs['TxnDateRangeFilter'] if 'TxnDateRangeFilter' in kwargs else None + self.DateMacro = None + if 'DateMacro' in kwargs: + if kwargs['DateMacro'] in ['All', 'Today', 'ThisWeek', 'ThisWeekToDate', 'ThisMonth', 'ThisMonthToDate', 'ThisQuarter', 'ThisQuarterToDate', 'ThisYear', 'ThisYearToDate', 'Yesterday', 'LastWeek', 'LastWeekToDate', 'LastMonth', 'LastMonthToDate', 'LastQuarter', 'LastQuarterToDate', 'LastYear', 'LastYearToDate', 'NextWeek', 'NextFourWeeks', 'NextMonth', 'NextQuarter', 'NextYear']: + self.DateMacro = kwargs['DateMacro'] + self.FromTxnDate = self.validate_date(kwargs['FromTxnDate']) if 'FromTxnDate' in kwargs else None + self.ToTxnDate = self.validate_date(kwargs['ToTxnDate']) if 'ToTxnDate' in kwargs else None + self.ReportEntityFilter = kwargs['ReportEntityFilter'] if 'ReportEntityFilter' in kwargs else None + self.FullName = kwargs['FullName'] if 'FullName' in kwargs else None + # print(self.DateMacro, self.TxnDateRangeFilter, self.FromTxnDate, self.ToTxnDate) + def create_sub_element(self, ET, parentNode, thisNode, text="\n", whiteSpace = 0, attrib =None): + if type(attrib) is not dict: + attrib = {} + ele = ET.SubElement(parentNode, thisNode) + for x in attrib: + ele.set(x, attrib[x]) + ele.text = text + tail = "\n" + for x in range(whiteSpace): + tail = tail + " " + ele.tail = tail + return ele + + def create_QBXML(self): + root = ET.Element("QBXML") + root.tail = "\n" + root.text = "\n " + QBXMLMsgsRq = ET.SubElement(root, "QBXMLMsgsRq") + # QBXMLMsgsRq.set("onError", "continueOnError") + QBXMLMsgsRq.set("onError", "stopOnError") + QBXMLMsgsRq.tail = "\n" + QBXMLMsgsRq.text = "\n " + UnitOfMeasureSetQueryRq = self.create_sub_element(ET, QBXMLMsgsRq, "UnitOfMeasureSetQueryRq","\n " ) + FullName = self.create_sub_element(ET, UnitOfMeasureSetQueryRq, "FullName", "Box of 12") + # NameFilter = self.create_sub_element(ET, UnitOfMeasureSetQueryRq, "NameFilter") + # MatchCriterion = self.create_sub_element(ET, NameFilter, "MatchCriterion", "StartsWith") + # Name = self.create_sub_element(ET, NameFilter, "Name", "Box of 12") + + mydata = ET.tostring(root, encoding = "unicode") + + qbxml_query = """\n""" + qbxml_query = qbxml_query + """""" + qbxml_query = qbxml_query + "\n" + mydata + print(qbxml_query) + + self.getConvertionRatio(self.connect_to_quickbooks(qbxml_query)) + return qbxml_query + + def connect_to_quickbooks(self, qbxml_query): + # Connect to Quickbooks + # sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + # sessionManager.OpenConnection('', 'DASA') + # enumfodnc= win32com.client.Dispatch('QBXMLRP2.RequestProcessor') + # print(enumfodnc) + # print(enumfodnc.qbFileOpenDoNotCare) + sessionManager = win32com.client.Dispatch("QBXMLRP2.RequestProcessor") + sessionManager.OpenConnection('', 'DASA2') + # ticket = sessionManager.BeginSession("z:\\DBW Bogor.qbw", 2) + + ticket = sessionManager.BeginSession("", 2) + + # Send query and receive response + response_string = sessionManager.ProcessRequest(ticket, qbxml_query) + + # Disconnect from Quickbooks + sessionManager.EndSession(ticket) # Close the company file + sessionManager.CloseConnection() # Close the connection + print (response_string) + return response_string + + def getConvertionRatio(self, response_string): + QBXML = ET.fromstring(response_string) + print(QBXML.findall('.//*[Name="Box"]/Name')) + print(QBXML.findall('.//Name[.="Box"]')[0].tag) + print(QBXML.findall('.//*[.="Box"]')[0].text) + + + print(QBXML.findtext("Box")) + +if __name__ == '__main__': + + + starttime = timeit.default_timer() + # ini=UnitOfMeasureSetQuery(DateMacro='ThisWeek', IncludeLineItems='true', RefNumber=["L2307-04429", "L2307-02992", 'L2307-03649',"L2307-02108", "L2307-03638"]) + ini=UnitOfMeasureSetQuery(DateMacro='ThisWeek', IncludeLineItems='true', RefNumber=["L2307-04429", "L2307-05899"]) + # ini=UnitOfMeasureSetQuery(DateMacro='ThisWeek', IncludeLineItems='true') + # # ini=UnitOfMeasureSetQuery(DateMacro='LastWeek', IncludeLineItems='true') + # print(ini.PurchaseOrderList) + ret=ini.create_QBXML() + print(ret) + # print(ini.connect_to_quickbooks(ini.create_QBXML)) + # ini.getConvertionRatio(ret) + print("The time difference is :", timeit.default_timer() - starttime) \ No newline at end of file diff --git a/readme b/readme new file mode 100644 index 0000000..e7a9147 --- /dev/null +++ b/readme @@ -0,0 +1,5 @@ +uvicorn --host 0.0.0.0 --port 9999 --reload main:app + +todo: +- change bgrlinedasa.py at raspi +- for folium, chagne the django mapping to accept form input asking FromDate and ToDate option. and drop down time ReportDateMacro diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b677ebe Binary files /dev/null and b/requirements.txt differ diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..7e8401f --- /dev/null +++ b/templates/base.html @@ -0,0 +1,175 @@ + + + + + + + Search Website1 + + + + + + + + + + + + + + + + + + + +
+ {% block content %}{% endblock %} +
+ + + + + + + + + + + + diff --git a/templates/hello.html b/templates/hello.html new file mode 100644 index 0000000..7f83928 --- /dev/null +++ b/templates/hello.html @@ -0,0 +1,5 @@ + + +

Hello World! {{name}}

+ + \ No newline at end of file diff --git a/templates/po_index.html b/templates/po_index.html new file mode 100644 index 0000000..dcfade1 --- /dev/null +++ b/templates/po_index.html @@ -0,0 +1,23 @@ + + + + + + Bootstrap demo + + + + +

Hello, world! {{name}}

+ + + diff --git a/templates/search_results.html b/templates/search_results.html new file mode 100644 index 0000000..b6d73b0 --- /dev/null +++ b/templates/search_results.html @@ -0,0 +1,33 @@ +{% extends "base.html" %} + +{% block content %} + + + + + + + + + + + + + + {% for result in results %} + + + + + + + + {% endfor %} + +
IDItem NameCustomer IDCustomer NameStart Date
{{ result.id }}{{ result.item_name }}{{ result.cust_id }}{{ result.cust_name }}{{ result.start_date }}
+ +{% endblock %} diff --git a/test request web.py b/test request web.py new file mode 100644 index 0000000..e8bac62 --- /dev/null +++ b/test request web.py @@ -0,0 +1,13 @@ +import requests +import json + +url = 'http://127.0.0.1:5555/getopenso' +myobj = {"CustomerName":"Al Malik Paint",} +myobj = json.dumps(myobj) +x = requests.post(url, json=myobj) +print(x.text) +url = 'http://127.0.0.1:5555/getopensodetail' +y={'solist':x.text} +y=json.dumps(y) +x = requests.post(url, json= y) +print(json.loads(x.text)) diff --git a/tools.py b/tools.py new file mode 100644 index 0000000..7e921ea --- /dev/null +++ b/tools.py @@ -0,0 +1,11 @@ +import string + +def get_alpha_numeric(text:str): + result="" + for x in text: + if x.isdecimal() or x.isalpha(): + result += x + return result + +if __name__ == "__main__": + print(get_alpha_numeric('TH-201/88. aa, BH')) \ No newline at end of file