Features: Combined all the list forms
Feautres: New Forms, Tax, Product TODO: Initial Sale Window testing with flow layout
This commit is contained in:
parent
d44daf921b
commit
196e556550
|
@ -0,0 +1,6 @@
|
|||
TODO: Authorization and Authentication
|
||||
TODO: User View == Proper has_permission handling
|
||||
TODO: Settings / Config module
|
||||
INFO: product now has a 'has_happy_hour' check box, if it is there, then show twice in list once as happy hour
|
||||
and one normal. in the sale also do the same. this will also make sure that the price is synced and if happy hour
|
||||
is being properly given
|
|
@ -0,0 +1,103 @@
|
|||
from PyQt5.QtCore import QPoint, QRect, QSize, Qt
|
||||
from PyQt5.QtWidgets import QLayout, QSizePolicy, QStyle
|
||||
|
||||
__author__ = 'tanshu'
|
||||
|
||||
|
||||
class FlowLayout(QLayout):
|
||||
def __init__(self, parent=None, margin=0, spacing=-1):
|
||||
super(FlowLayout, self).__init__(parent)
|
||||
|
||||
if parent is not None:
|
||||
self.setContentsMargins(margin, margin, margin, margin)
|
||||
|
||||
self.setSpacing(spacing)
|
||||
|
||||
self.itemList = []
|
||||
|
||||
def __del__(self):
|
||||
item = self.takeAt(0)
|
||||
while item:
|
||||
item = self.takeAt(0)
|
||||
|
||||
def addItem(self, item):
|
||||
self.itemList.append(item)
|
||||
|
||||
def count(self):
|
||||
return len(self.itemList)
|
||||
|
||||
def itemAt(self, index):
|
||||
if index >= 0 and index < len(self.itemList):
|
||||
return self.itemList[index]
|
||||
|
||||
return None
|
||||
|
||||
def takeAt(self, index):
|
||||
if index >= 0 and index < len(self.itemList):
|
||||
return self.itemList.pop(index)
|
||||
|
||||
return None
|
||||
|
||||
def expandingDirections(self):
|
||||
return Qt.Orientations(Qt.Orientation(0))
|
||||
|
||||
def hasHeightForWidth(self):
|
||||
return True
|
||||
|
||||
def heightForWidth(self, width):
|
||||
height = self.doLayout(QRect(0, 0, width, 0), True)
|
||||
return height
|
||||
|
||||
def setGeometry(self, rect):
|
||||
super(FlowLayout, self).setGeometry(rect)
|
||||
self.doLayout(rect, False)
|
||||
|
||||
def sizeHint(self):
|
||||
return self.minimumSize()
|
||||
|
||||
def minimumSize(self):
|
||||
size = QSize()
|
||||
|
||||
for item in self.itemList:
|
||||
size = size.expandedTo(item.minimumSize())
|
||||
|
||||
margin, _, _, _ = self.getContentsMargins()
|
||||
|
||||
size += QSize(2 * margin, 2 * margin)
|
||||
return size
|
||||
|
||||
def horizontalSpacing(self):
|
||||
return self.smartSpacing(QStyle.PM_LayoutHorizontalSpacing)
|
||||
|
||||
def verticalSpacing(self):
|
||||
return self.smartSpacing(QStyle.PM_LayoutVerticalSpacing)
|
||||
|
||||
def doLayout(self, rect, testOnly):
|
||||
left, top, right, bottom = self.getContentsMargins()
|
||||
effectiveRect = rect.adjusted(+left, +top, -right, -bottom)
|
||||
x = effectiveRect.x()
|
||||
y = effectiveRect.y()
|
||||
lineHeight = 0
|
||||
|
||||
for item in self.itemList:
|
||||
wid = item.widget()
|
||||
if wid.isHidden():
|
||||
continue
|
||||
spaceX = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton,
|
||||
Qt.Horizontal)
|
||||
spaceY = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton,
|
||||
Qt.Vertical)
|
||||
nextX = x + item.sizeHint().width() + spaceX
|
||||
if nextX - spaceX > rect.right() and lineHeight > 0:
|
||||
x = rect.x()
|
||||
y = y + lineHeight + spaceY
|
||||
nextX = x + item.sizeHint().width() + spaceX
|
||||
lineHeight = 0
|
||||
|
||||
if not testOnly:
|
||||
item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
|
||||
|
||||
x = nextX
|
||||
lineHeight = max(lineHeight, item.sizeHint().height())
|
||||
|
||||
return y + lineHeight - rect.y()
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>RoleList</class>
|
||||
<widget class="QMainWindow" name="RoleList">
|
||||
<class>ListForm</class>
|
||||
<widget class="QMainWindow" name="ListForm">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
</property>
|
||||
|
@ -14,17 +14,17 @@
|
|||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Roles</string>
|
||||
<string>List Form</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QTableView" name="tblRoles"/>
|
||||
<widget class="QTableView" name="tblItems"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="btnAddNew">
|
||||
<property name="text">
|
||||
<string>Add Role</string>
|
||||
<string>Add Item</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
|
@ -251,8 +251,8 @@
|
|||
<widget class="QPushButton" name="btnExit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>650</x>
|
||||
<y>340</y>
|
||||
<x>10</x>
|
||||
<y>450</y>
|
||||
<width>150</width>
|
||||
<height>100</height>
|
||||
</rect>
|
||||
|
@ -274,6 +274,19 @@
|
|||
<string>Management</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="btnTaxes">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>650</x>
|
||||
<y>340</y>
|
||||
<width>150</width>
|
||||
<height>100</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Taxes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
|
@ -297,6 +310,7 @@
|
|||
<tabstop>btnDiscountReport</tabstop>
|
||||
<tabstop>btnChangePassword</tabstop>
|
||||
<tabstop>btnManagement</tabstop>
|
||||
<tabstop>btnTaxes</tabstop>
|
||||
<tabstop>btnExit</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ProductDetails</class>
|
||||
<widget class="QDialog" name="ProductDetails">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>397</width>
|
||||
<height>417</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Product Details</string>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="txtName"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="txtUnits"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Group</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="cmbProductGroup"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Price</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QDoubleSpinBox" name="dsbPrice"/>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="chkHasHappyHour">
|
||||
<property name="text">
|
||||
<string>Has Happy Hour?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Service Charge</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QDoubleSpinBox" name="dsbServiceCharge"/>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QCheckBox" name="chkScTaxable">
|
||||
<property name="text">
|
||||
<string>Is Service Charge Taxable?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Service Tax</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QComboBox" name="cmbServiceTax"/>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>VAT</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QComboBox" name="cmbVat"/>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Sort Order</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QSpinBox" name="sbSortOrder"/>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QCheckBox" name="chkIsActive">
|
||||
<property name="text">
|
||||
<string>Is Active?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>txtName</tabstop>
|
||||
<tabstop>txtUnits</tabstop>
|
||||
<tabstop>cmbProductGroup</tabstop>
|
||||
<tabstop>dsbPrice</tabstop>
|
||||
<tabstop>chkHasHappyHour</tabstop>
|
||||
<tabstop>dsbServiceCharge</tabstop>
|
||||
<tabstop>chkScTaxable</tabstop>
|
||||
<tabstop>cmbServiceTax</tabstop>
|
||||
<tabstop>cmbVat</tabstop>
|
||||
<tabstop>sbSortOrder</tabstop>
|
||||
<tabstop>chkIsActive</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ProductDetails</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>227</x>
|
||||
<y>331</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ProductDetails</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>295</x>
|
||||
<y>337</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -1,37 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ProductGroupList</class>
|
||||
<widget class="QMainWindow" name="ProductGroupList">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Product Groups</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QTableView" name="tblProductGroups"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="btnAddNew">
|
||||
<property name="text">
|
||||
<string>Add Product Group</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,68 @@
|
|||
from PyQt5 import QtCore, QtWidgets
|
||||
|
||||
from summer.QtDesignerFiles.FlowLayout import FlowLayout
|
||||
|
||||
|
||||
class SaleWindowQt(object):
|
||||
def setupUi(self, SaleWindow):
|
||||
SaleWindow.setObjectName("SaleWindow")
|
||||
SaleWindow.resize(1024, 768)
|
||||
self.centralwidget = QtWidgets.QWidget(SaleWindow)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
|
||||
self.tableView = QtWidgets.QTableView(self.centralwidget)
|
||||
self.tableView.setGeometry(QtCore.QRect(10, 10, 400, 550))
|
||||
self.tableView.setObjectName("tableView")
|
||||
|
||||
self.abWidget = QtWidgets.QWidget(self.centralwidget)
|
||||
self.abWidget.setGeometry(QtCore.QRect(10, 620, 1004, 140))
|
||||
self.abWidget.setObjectName("abWidget")
|
||||
self.flActions = FlowLayout(self.abWidget)
|
||||
self.flActions.setContentsMargins(0, 0, 0, 0)
|
||||
self.flActions.setObjectName("flActions")
|
||||
|
||||
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
|
||||
self.verticalLayoutWidget.setGeometry(QtCore.QRect(909, 10, 101, 641))
|
||||
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
|
||||
self.vlGroups = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
|
||||
self.vlGroups.setContentsMargins(0, 0, 0, 0)
|
||||
self.vlGroups.setObjectName("vlGroups")
|
||||
self.pushButton_9 = QtWidgets.QPushButton(self.verticalLayoutWidget)
|
||||
self.pushButton_9.setObjectName("pushButton_9")
|
||||
self.vlGroups.addWidget(self.pushButton_9)
|
||||
self.pushButton_8 = QtWidgets.QPushButton(self.verticalLayoutWidget)
|
||||
self.pushButton_8.setObjectName("pushButton_8")
|
||||
self.vlGroups.addWidget(self.pushButton_8)
|
||||
|
||||
self.mbWidget = QtWidgets.QWidget(self.centralwidget)
|
||||
self.mbWidget.setGeometry(QtCore.QRect(420, 10, 510, 550))
|
||||
self.mbWidget.setObjectName("mbWidget")
|
||||
self.flMainButtons = FlowLayout(self.mbWidget)
|
||||
self.flMainButtons.setContentsMargins(0, 0, 0, 0)
|
||||
self.flMainButtons.setObjectName("flMainButtons")
|
||||
|
||||
SaleWindow.setCentralWidget(self.centralwidget)
|
||||
self.statusbar = QtWidgets.QStatusBar(SaleWindow)
|
||||
self.statusbar.setObjectName("statusbar")
|
||||
SaleWindow.setStatusBar(self.statusbar)
|
||||
|
||||
self.retranslateUi(SaleWindow)
|
||||
QtCore.QMetaObject.connectSlotsByName(SaleWindow)
|
||||
|
||||
def retranslateUi(self, SaleWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
SaleWindow.setWindowTitle(_translate("SaleWindow", "MainWindow"))
|
||||
self.pushButton_9.setText(_translate("SaleWindow", "PushButton"))
|
||||
self.pushButton_8.setText(_translate("SaleWindow", "PushButton"))
|
||||
|
||||
def add_action(self, button, title, action):
|
||||
act = QtWidgets.QPushButton(self.horizontalLayoutWidget)
|
||||
act.setObjectName(button)
|
||||
act.clicked.connect(action)
|
||||
act.setText(title)
|
||||
self.flActions.addWidget(act)
|
||||
self.actions[button] = act
|
||||
|
||||
def remove_action(self, button):
|
||||
if button in self.actions:
|
||||
del self.actions[button]
|
|
@ -0,0 +1,98 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TaxDetails</class>
|
||||
<widget class="QDialog" name="TaxDetails">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>397</width>
|
||||
<height>231</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Tax Details</string>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="txtName"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Rate %</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="dsbRate"/>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>txtName</tabstop>
|
||||
<tabstop>dsbRate</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>TaxDetails</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>227</x>
|
||||
<y>331</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>TaxDetails</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>295</x>
|
||||
<y>337</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -1,37 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UserList</class>
|
||||
<widget class="QMainWindow" name="UserList">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Users</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QTableView" name="tblUsers"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="btnAddNew">
|
||||
<property name="text">
|
||||
<string>Add User</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -7,8 +7,8 @@ from sqlalchemy.schema import ForeignKey, Table
|
|||
from sqlalchemy import Column, Boolean, Unicode
|
||||
from sqlalchemy.orm import synonym, relationship
|
||||
|
||||
from models.guidtype import GUID
|
||||
from models import Base
|
||||
from summer.models.guidtype import GUID
|
||||
from summer.models import Base
|
||||
|
||||
|
||||
def encrypt(val):
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
__author__ = 'tanshu'
|
||||
|
||||
import uuid
|
||||
|
||||
from sqlalchemy import UniqueConstraint, Column, Integer, Unicode, Numeric, Boolean, ForeignKey, func, PickleType
|
||||
from sqlalchemy.orm import relationship
|
||||
from models import Base
|
||||
from models.guidtype import GUID
|
||||
|
||||
from summer.models import Base
|
||||
from summer.models.guidtype import GUID
|
||||
|
||||
|
||||
class Product(Base):
|
||||
|
@ -30,15 +32,14 @@ class Product(Base):
|
|||
service_tax = relationship('Tax', foreign_keys=service_tax_id, backref='products_service_tax')
|
||||
vat = relationship('Tax', foreign_keys=vat_id, backref='products_vat')
|
||||
|
||||
def __init__(self, code=None, name=None, units=None, product_group_id=None, price=None, happy_hour=None,
|
||||
def __init__(self, name=None, units=None, product_group_id=None, price=None, has_happy_hour=None,
|
||||
service_tax_id=None, vat_id=None, service_charge=None, sc_taxable=None, is_active=None,
|
||||
sort_order=None, is_fixture=False):
|
||||
self.code = code
|
||||
self.name = name
|
||||
self.units = units
|
||||
self.product_group_id = product_group_id
|
||||
self.price = price
|
||||
self.happy_hour = happy_hour
|
||||
self.has_happy_hour = has_happy_hour
|
||||
self.service_tax_id = service_tax_id
|
||||
self.vat_id = vat_id
|
||||
self.service_charge = service_charge
|
||||
|
@ -52,8 +53,8 @@ class Product(Base):
|
|||
return "{0} ({1})".format(self.name, self.units)
|
||||
|
||||
@classmethod
|
||||
def list(cls, name, active, *, DBSession=None):
|
||||
query = DBSession.query(cls)
|
||||
def list(cls, name, active, *, session=None):
|
||||
query = session.query(cls)
|
||||
if active is not None:
|
||||
query = query.filter(cls.is_active != active)
|
||||
for item in name.split():
|
||||
|
@ -61,28 +62,28 @@ class Product(Base):
|
|||
return query.order_by(cls.name)
|
||||
|
||||
@classmethod
|
||||
def by_name(cls, name, *, DBSession=None):
|
||||
return DBSession.query(cls).filter(cls.name == name).first()
|
||||
def by_name(cls, name, *, session=None):
|
||||
return session.query(cls).filter(cls.name == name).first()
|
||||
|
||||
@classmethod
|
||||
def by_full_name(cls, full_name, *, DBSession=None):
|
||||
return DBSession.query(cls).filter(cls.name + ' (' + cls.units + ')' == full_name).first()
|
||||
def by_full_name(cls, full_name, *, session=None):
|
||||
return session.query(cls).filter(cls.name + ' (' + cls.units + ')' == full_name).first()
|
||||
|
||||
@classmethod
|
||||
def by_id(cls, id, *, DBSession=None):
|
||||
return DBSession.query(cls).filter(cls.id == id).first()
|
||||
def by_id(cls, id, *, session=None):
|
||||
return session.query(cls).filter(cls.id == id).first()
|
||||
|
||||
@classmethod
|
||||
def query(cls, *, DBSession=None):
|
||||
return DBSession.query(cls)
|
||||
def query(cls, *, session=None):
|
||||
return session.query(cls)
|
||||
|
||||
def create(self, *, DBSession=None):
|
||||
code = DBSession.query(func.max(Product.code)).one()[0]
|
||||
def create(self, *, session=None):
|
||||
code = session.query(func.max(Product.code)).one()[0]
|
||||
if code is None:
|
||||
self.code = 1
|
||||
else:
|
||||
self.code = code + 1
|
||||
DBSession.add(self)
|
||||
session.add(self)
|
||||
return self
|
||||
|
||||
def can_delete(self, advanced_delete):
|
||||
|
@ -126,7 +127,7 @@ class ProductGroup(Base):
|
|||
self.is_fixture = is_fixture
|
||||
|
||||
@classmethod
|
||||
def by_id(cls, id, * , session=None):
|
||||
def by_id(cls, id, *, session=None):
|
||||
if not isinstance(id, uuid.UUID):
|
||||
id = uuid.UUID(id)
|
||||
return session.query(cls).filter(cls.id == id).first()
|
||||
|
@ -134,8 +135,8 @@ class ProductGroup(Base):
|
|||
def can_delete(self, advanced_delete):
|
||||
if self.is_fixture:
|
||||
return False, ('Fixture', "{0} cannot be edited or deleted.".format(self.name))
|
||||
#if len(self.inventories) > 0 and not advanced_delete:
|
||||
# return False, 'Product has entries'
|
||||
# if len(self.inventories) > 0 and not advanced_delete:
|
||||
# return False, 'Product has entries'
|
||||
return True, ''
|
||||
|
||||
|
||||
|
@ -156,23 +157,23 @@ class Tax(Base):
|
|||
self.is_fixture = is_fixture
|
||||
|
||||
@classmethod
|
||||
def by_id(cls, id):
|
||||
def by_id(cls, id, *, session=None):
|
||||
if not isinstance(id, uuid.UUID):
|
||||
id = uuid.UUID(id)
|
||||
return DBSession.query(cls).filter(cls.id == id).first()
|
||||
return session.query(cls).filter(cls.id == id).first()
|
||||
|
||||
@classmethod
|
||||
def by_name(cls, name):
|
||||
return DBSession.query(cls).filter(cls.name == name).first()
|
||||
def by_name(cls, name, *, session=None):
|
||||
return session.query(cls).filter(cls.name == name).first()
|
||||
|
||||
@classmethod
|
||||
def list(cls):
|
||||
return DBSession.query(cls).order_by(cls.name).all()
|
||||
def list(cls, *, session=None):
|
||||
return session.query(cls).order_by(cls.name).all()
|
||||
|
||||
def can_delete(self, advanced_delete):
|
||||
if self.is_fixture:
|
||||
return False, ('Fixture', "{0} cannot be edited or deleted.".format(self.name))
|
||||
#if len(self.inventories) > 0 and not advanced_delete:
|
||||
# if len(self.inventories) > 0 and not advanced_delete:
|
||||
# return False, 'Product has entries'
|
||||
return True, ''
|
||||
|
||||
|
@ -243,7 +244,7 @@ class FoodTable(Base):
|
|||
return DBSession.query(cls).order_by(cls.name).all()
|
||||
|
||||
def can_delete(self, advanced_delete):
|
||||
#if len(self.inventories) > 0 and not advanced_delete:
|
||||
# if len(self.inventories) > 0 and not advanced_delete:
|
||||
# return False, 'Product has entries'
|
||||
return True, ''
|
||||
|
||||
|
@ -306,7 +307,7 @@ class Modifier(Base):
|
|||
return DBSession.query(cls).order_by(cls.name).all()
|
||||
|
||||
def can_delete(self, advanced_delete):
|
||||
#if len(self.inventories) > 0 and not advanced_delete:
|
||||
# if len(self.inventories) > 0 and not advanced_delete:
|
||||
# return False, 'Product has entries'
|
||||
return True, ''
|
||||
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
import json
|
||||
|
||||
__author__ = 'tanshu'
|
||||
|
||||
from sqlalchemy.exc import OperationalError, IntegrityError
|
||||
|
||||
|
||||
class ValidationError(Exception):
|
||||
def __init__(self, header, message, Errors=None):
|
||||
self.header = header
|
||||
def __init__(self, message, Errors=None):
|
||||
self.message = message
|
||||
# Call the base class constructor with the parameters it needs
|
||||
Exception.__init__(self, (header, message))
|
||||
Exception.__init__(self, message)
|
||||
|
||||
# Now for your custom code...
|
||||
self.Errors = Errors
|
||||
|
@ -19,22 +14,4 @@ class ValidationError(Exception):
|
|||
return self.message
|
||||
|
||||
def json(self):
|
||||
return (self.header, self.message)
|
||||
#
|
||||
#
|
||||
# def TryCatchFunction(f):
|
||||
# def _decorator(self, *args, **kwargs):
|
||||
# try:
|
||||
# return f(self, *args, **kwargs)
|
||||
# except ValidationError as ex:
|
||||
# transaction.abort()
|
||||
# response = Response(json.dumps(ex.json()))
|
||||
# response.status_int = 500
|
||||
# return response
|
||||
# except (ValueError, KeyError, AttributeError, TypeError, OperationalError, IntegrityError) as ex:
|
||||
# transaction.abort()
|
||||
# response = Response(json.dumps(('Failed validation', str(ex))))
|
||||
# response.status_int = 500
|
||||
# return response
|
||||
#
|
||||
# return _decorator
|
||||
return self.message
|
||||
|
|
|
@ -6,9 +6,9 @@ from sqlalchemy.ext.hybrid import hybrid_property
|
|||
from sqlalchemy import Column, Integer, DateTime, Numeric, ForeignKey, Boolean, UniqueConstraint
|
||||
from sqlalchemy.orm import relationship, synonym, backref
|
||||
|
||||
from models.master import Tax
|
||||
from models.guidtype import GUID
|
||||
from models import Base
|
||||
from summer.models.master import Tax
|
||||
from summer.models.guidtype import GUID
|
||||
from summer.models import Base
|
||||
|
||||
|
||||
class VoucherType:
|
||||
|
|
|
@ -7,15 +7,17 @@ from PyQt5 import uic
|
|||
file = '/home/tanshu/Programming/summer/summer/QtDesignerFiles/MainWindow.ui'
|
||||
base, form = uic.loadUiType(file)
|
||||
|
||||
|
||||
class MainWindow(base, form):
|
||||
def __init__(self, router, parent=None):
|
||||
super(MainWindow, self).__init__()
|
||||
self.setupUi(self)
|
||||
self.btnExit.clicked.connect(self.handle_exit)
|
||||
self.btnUsers.clicked.connect(router.show_users)
|
||||
self.btnSales.clicked.connect(router.show_sales)
|
||||
self.btnRoles.clicked.connect(router.show_roles)
|
||||
self.btnProductGroups.clicked.connect(router.show_product_groups)
|
||||
self.btnTaxes.clicked.connect(router.show_taxes)
|
||||
self.btnProducts.clicked.connect(router.show_products)
|
||||
|
||||
def handle_exit(self):
|
||||
self.close()
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
__author__ = 'tanshu'
|
||||
from PyQt5 import uic, QtCore
|
||||
|
||||
|
||||
file = '/home/tanshu/Programming/summer/summer/QtDesignerFiles/ProductDetail.ui'
|
||||
base, form = uic.loadUiType(file)
|
||||
|
||||
|
||||
class ProductDetail(base, form):
|
||||
def __init__(self, router, product, product_groups, taxes, parent=None):
|
||||
super(ProductDetail, self).__init__()
|
||||
self.setupUi(self)
|
||||
self.router = router
|
||||
self.product = product
|
||||
self.txtName.setText(product['Name'])
|
||||
self.txtUnits.setText(product['Units'])
|
||||
self.product_group_model = ProductGroupModel(product_groups)
|
||||
self.cmbProductGroup.setModel(self.product_group_model)
|
||||
pg_index = [i for (i, d) in enumerate(product_groups) if
|
||||
d['ProductGroupID'] == product['ProductGroup']['ProductGroupID']]
|
||||
if len(pg_index) != 0:
|
||||
self.cmbProductGroup.setCurrentIndex(pg_index[0])
|
||||
|
||||
self.dsbPrice.setMinimum(0)
|
||||
self.dsbPrice.setValue(product['Price'])
|
||||
self.chkHasHappyHour.setCheckState(QtCore.Qt.Checked if product['HasHappyHour'] else QtCore.Qt.Unchecked)
|
||||
|
||||
self.service_tax_model = TaxModel(taxes)
|
||||
self.cmbServiceTax.setModel(self.service_tax_model)
|
||||
st_index = [i for (i, d) in enumerate(taxes) if d['TaxID'] == product['ServiceTax']['TaxID']]
|
||||
if len(st_index) != 0:
|
||||
self.cmbServiceTax.setCurrentIndex(st_index[0])
|
||||
|
||||
self.vat_model = TaxModel(taxes)
|
||||
self.cmbVat.setModel(self.vat_model)
|
||||
vat_index = [i for (i, d) in enumerate(taxes) if d['TaxID'] == product['Vat']['TaxID']]
|
||||
if len(vat_index) != 0:
|
||||
self.cmbVat.setCurrentIndex(vat_index[0])
|
||||
|
||||
self.dsbServiceCharge.setMinimum(0)
|
||||
self.dsbServiceCharge.setValue(product['ServiceCharge'])
|
||||
self.chkScTaxable.setCheckState(QtCore.Qt.Checked if product['ScTaxable'] else QtCore.Qt.Unchecked)
|
||||
self.chkIsActive.setCheckState(QtCore.Qt.Checked if product['IsActive'] else QtCore.Qt.Unchecked)
|
||||
self.sbSortOrder.setMinimum(0)
|
||||
self.sbSortOrder.setValue(product['SortOrder'])
|
||||
self.accepted.connect(self.save_product)
|
||||
self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
|
||||
|
||||
def save_product(self):
|
||||
self.product['Name'] = self.txtName.text()
|
||||
self.product['Units'] = self.txtUnits.text()
|
||||
self.product['ProductGroup'] = self.cmbProductGroup.currentData()
|
||||
self.product['Price'] = self.dsbPrice.value()
|
||||
self.product['HasHappyHour'] = self.chkHasHappyHour.isChecked()
|
||||
self.product['ServiceTax'] = self.cmbServiceTax.currentData()
|
||||
self.product['Vat'] = self.cmbVat.currentData()
|
||||
self.product['ServiceCharge'] = self.dsbServiceCharge.value() / 100
|
||||
self.product['ScTaxable'] = self.chkScTaxable.isChecked()
|
||||
self.product['IsActive'] = self.chkIsActive.isChecked()
|
||||
self.product['SortOrder'] = self.sbSortOrder.value()
|
||||
|
||||
self.router.save_product(self.product)
|
||||
|
||||
|
||||
class ProductGroupModel(QtCore.QAbstractListModel):
|
||||
def __init__(self, product_groups=None, parent=None):
|
||||
QtCore.QAbstractListModel.__init__(self, parent)
|
||||
self.product_groups = product_groups if product_groups is not None else []
|
||||
|
||||
def rowCount(self, parent):
|
||||
return len(self.product_groups)
|
||||
|
||||
def data(self, index, role):
|
||||
if role == QtCore.Qt.DisplayRole:
|
||||
item = self.product_groups[index.row()]
|
||||
return item['Name']
|
||||
if role == QtCore.Qt.UserRole:
|
||||
return self.product_groups[index.row()]
|
||||
|
||||
def headerData(self, section, orientation, role):
|
||||
if role == QtCore.Qt.DisplayRole:
|
||||
if orientation == QtCore.Qt.Horizontal:
|
||||
return 'Product Groups'
|
||||
else:
|
||||
return section + 1
|
||||
|
||||
|
||||
class TaxModel(QtCore.QAbstractListModel):
|
||||
def __init__(self, taxes=None, parent=None):
|
||||
QtCore.QAbstractListModel.__init__(self, parent)
|
||||
self.taxes = taxes if taxes is not None else []
|
||||
|
||||
def rowCount(self, parent):
|
||||
return len(self.taxes)
|
||||
|
||||
def data(self, index, role):
|
||||
if role == QtCore.Qt.DisplayRole:
|
||||
item = self.taxes[index.row()]
|
||||
return item['Name'] + ' ' + '({0:,.2f}%)'.format(item['Rate'] * 100)
|
||||
if role == QtCore.Qt.UserRole:
|
||||
return self.taxes[index.row()]
|
||||
|
||||
def headerData(self, section, orientation, role):
|
||||
if role == QtCore.Qt.DisplayRole:
|
||||
if orientation == QtCore.Qt.Horizontal:
|
||||
return 'Taxes'
|
||||
else:
|
||||
return section + 1
|
|
@ -2,7 +2,7 @@ __author__ = 'tanshu'
|
|||
from PyQt5 import uic, QtCore, QtWidgets
|
||||
|
||||
|
||||
file = '/home/tanshu/Programming/summer/summer/QtDesignerFiles/ProductGroupList.ui'
|
||||
file = '/home/tanshu/Programming/summer/summer/QtDesignerFiles/ListForm.ui'
|
||||
base, form = uic.loadUiType(file)
|
||||
|
||||
|
||||
|
@ -10,19 +10,26 @@ class ProductGroupList(base, form):
|
|||
def __init__(self, router, product_groups, parent=None):
|
||||
super(ProductGroupList, self).__init__()
|
||||
self.setupUi(self)
|
||||
self.translateUi()
|
||||
self.router = router
|
||||
self.product_groups = product_groups
|
||||
self.model = ProductGroupsTableModel(product_groups)
|
||||
self.tblProductGroups.setModel(self.model)
|
||||
self.tblProductGroups.doubleClicked.connect(self.show_product_group)
|
||||
self.tblItems.setModel(self.model)
|
||||
self.tblItems.doubleClicked.connect(self.show_product_group)
|
||||
self.btnAddNew.clicked.connect(self.add_new_product_group)
|
||||
self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
|
||||
self.tblProductGroups.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||
self.tblItems.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||
|
||||
def translateUi(self):
|
||||
self.setObjectName("ProductGroupList")
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
self.setWindowTitle(_translate("ListForm", "Product Groups"))
|
||||
self.btnAddNew.setText(_translate("ListForm", "Add Product Group"))
|
||||
|
||||
def update_data(self, data):
|
||||
self.product_groups = data
|
||||
self.model = ProductGroupsTableModel(self.product_groups)
|
||||
self.tblProductGroups.setModel(self.model)
|
||||
self.tblItems.setModel(self.model)
|
||||
|
||||
def show_product_group(self, index):
|
||||
product_group = self.model.product_groups[index.row()]
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
__author__ = 'tanshu'
|
||||
from PyQt5 import uic, QtCore, QtWidgets
|
||||
|
||||
|
||||
file = '/home/tanshu/Programming/summer/summer/QtDesignerFiles/ListForm.ui'
|
||||
base, form = uic.loadUiType(file)
|
||||
|
||||
|
||||
class ProductList(base, form):
|
||||
def __init__(self, router, products, parent=None):
|
||||
super(ProductList, self).__init__()
|
||||
self.setupUi(self)
|
||||
self.translateUi()
|
||||
self.router = router
|
||||
self.products = products
|
||||
self.model = ProductsTableModel(products)
|
||||
self.tblItems.setModel(self.model)
|
||||
self.tblItems.doubleClicked.connect(self.show_product)
|
||||
self.btnAddNew.clicked.connect(self.add_new_product)
|
||||
self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
|
||||
self.tblItems.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||
|
||||
def translateUi(self):
|
||||
self.setObjectName("ProductList")
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
self.setWindowTitle(_translate("ListForm", "Products"))
|
||||
self.btnAddNew.setText(_translate("ListForm", "Add Product"))
|
||||
|
||||
def update_data(self, data):
|
||||
self.products = data
|
||||
self.model = ProductsTableModel(self.products)
|
||||
self.tblItems.setModel(self.model)
|
||||
|
||||
def show_product(self, index):
|
||||
product = self.model.products[index.row()]
|
||||
self.router.show_product(product['ProductID'])
|
||||
|
||||
def add_new_product(self):
|
||||
self.router.show_product(None)
|
||||
|
||||
|
||||
class ProductsTableModel(QtCore.QAbstractTableModel):
|
||||
def __init__(self, products=None, parent=None):
|
||||
QtCore.QAbstractTableModel.__init__(self, parent)
|
||||
self.products = products if products is not None else []
|
||||
|
||||
def rowCount(self, parent):
|
||||
return len(self.products)
|
||||
|
||||
def columnCount(self, parent):
|
||||
return 12
|
||||
|
||||
def data(self, index, role):
|
||||
if role == QtCore.Qt.DisplayRole:
|
||||
item = self.products[index.row()]
|
||||
column = index.column()
|
||||
if column == 0:
|
||||
return item['Name']
|
||||
elif column == 1:
|
||||
return item['Units']
|
||||
elif column == 2:
|
||||
return item['ProductGroup']['Name']
|
||||
elif column == 3:
|
||||
return '{0:,.2f}'.format(item['Price'])
|
||||
elif column == 4:
|
||||
return item['HasHappyHour']
|
||||
elif column == 5:
|
||||
return item['ServiceTax']['Name'] + ' ' + '({0:,.2f}%)'.format(item['ServiceTax']['Rate'] * 100)
|
||||
elif column == 6:
|
||||
return item['Vat']['Name'] + ' ' + '({0:,.2f}%)'.format(item['Vat']['Rate'] * 100)
|
||||
elif column == 7:
|
||||
return '{0:,.2f}%'.format(item['ServiceCharge'] * 100)
|
||||
elif column == 8:
|
||||
return item['ScTaxable']
|
||||
elif column == 9:
|
||||
return item['IsActive']
|
||||
elif column == 10:
|
||||
return item['IsFixture']
|
||||
elif column == 11:
|
||||
return item['SortOrder']
|
||||
|
||||
def headerData(self, section, orientation, role):
|
||||
if role == QtCore.Qt.DisplayRole:
|
||||
if orientation == QtCore.Qt.Horizontal:
|
||||
if section == 0:
|
||||
return 'Name'
|
||||
elif section == 1:
|
||||
return 'Units'
|
||||
elif section == 2:
|
||||
return 'Product Group'
|
||||
elif section == 3:
|
||||
return 'Price'
|
||||
elif section == 4:
|
||||
return 'Has Happy Hour'
|
||||
elif section == 5:
|
||||
return 'Service Tax'
|
||||
elif section == 6:
|
||||
return 'Vat'
|
||||
elif section == 7:
|
||||
return 'Service Charge'
|
||||
elif section == 8:
|
||||
return 'Is Sc Taxable?'
|
||||
elif section == 9:
|
||||
return 'Is Active?'
|
||||
elif section == 10:
|
||||
return 'Is Fixture?'
|
||||
elif section == 11:
|
||||
return 'Sort Order'
|
||||
else:
|
||||
return section + 1
|
|
@ -2,7 +2,7 @@ __author__ = 'tanshu'
|
|||
from PyQt5 import uic, QtCore, QtWidgets
|
||||
|
||||
|
||||
file = '/home/tanshu/Programming/summer/summer/QtDesignerFiles/RoleList.ui'
|
||||
file = '/home/tanshu/Programming/summer/summer/QtDesignerFiles/ListForm.ui'
|
||||
base, form = uic.loadUiType(file)
|
||||
|
||||
|
||||
|
@ -10,19 +10,26 @@ class RoleList(base, form):
|
|||
def __init__(self, router, roles, parent=None):
|
||||
super(RoleList, self).__init__()
|
||||
self.setupUi(self)
|
||||
self.translateUi()
|
||||
self.router = router
|
||||
self.roles = roles
|
||||
self.model = RolesTableModel(roles)
|
||||
self.tblRoles.setModel(self.model)
|
||||
self.tblRoles.doubleClicked.connect(self.show_role)
|
||||
self.tblItems.setModel(self.model)
|
||||
self.tblItems.doubleClicked.connect(self.show_role)
|
||||
self.btnAddNew.clicked.connect(self.add_new_role)
|
||||
self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
|
||||
self.tblRoles.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||
self.tblItems.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||
|
||||
def translateUi(self):
|
||||
self.setObjectName("RoleList")
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
self.setWindowTitle(_translate("ListForm", "Roles"))
|
||||
self.btnAddNew.setText(_translate("ListForm", "Add Role"))
|
||||
|
||||
def update_data(self, data):
|
||||
self.roles = data
|
||||
self.model = RolesTableModel(self.roles)
|
||||
self.tblRoles.setModel(self.model)
|
||||
self.tblItems.setModel(self.model)
|
||||
|
||||
def show_role(self, index):
|
||||
role = self.model.roles[index.row()]
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
from PyQt5 import QtCore, QtWidgets
|
||||
|
||||
from summer.QtDesignerFiles.SaleWindow import SaleWindowQt
|
||||
|
||||
|
||||
__author__ = 'tanshu'
|
||||
|
||||
|
||||
class SaleWindow(SaleWindowQt, QtWidgets.QMainWindow):
|
||||
def __init__(self, router, parent=None):
|
||||
super(SaleWindow, self).__init__()
|
||||
self.setupUi(self)
|
||||
self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
|
||||
self.actionButtons = []
|
||||
self.mainButtons = []
|
||||
self.fillActionBar()
|
||||
self.fillMainButtons()
|
||||
|
||||
def addButton(self, widget, layout, name, text, connect=None):
|
||||
button = QtWidgets.QPushButton(widget)
|
||||
button.setObjectName(name)
|
||||
button.setText(text)
|
||||
button.setMinimumSize(75, 75)
|
||||
button.setMaximumSize(75, 75)
|
||||
layout.addWidget(button)
|
||||
if connect is not None:
|
||||
button.clicked.connect(connect(button))
|
||||
return button
|
||||
|
||||
def addActionButton(self, name, text, connect=None):
|
||||
button = self.addButton(self.abWidget, self.flActions, name, text, connect)
|
||||
self.actionButtons.append(button)
|
||||
|
||||
def fillActionBar(self):
|
||||
buttons = [
|
||||
('quantity', 'Quantity'),
|
||||
('delete', 'Delete'),
|
||||
('discount', 'Discount - F3'),
|
||||
('modifier', 'Modifier'),
|
||||
('waiter', 'Waiter - F5'),
|
||||
('print_kot', 'Print KOT - F12'),
|
||||
('print_bill', 'Print Bill - F11'),
|
||||
('clear', 'Clear - Esc'),
|
||||
('settle_bill', 'Settle Bill'),
|
||||
('rate', 'Rate'),
|
||||
('move_table', 'Move Table'),
|
||||
('void_bill', 'Void Bill'),
|
||||
('move_kot', 'Move KOT'),
|
||||
('split_bill', 'Split Bill')
|
||||
]
|
||||
for name, text in buttons:
|
||||
self.addActionButton(name, text, self.hide_button)
|
||||
|
||||
|
||||
def addMainButton(self, name, text, connect=None):
|
||||
button = self.addButton(self.mbWidget, self.flMainButtons, name, text, connect)
|
||||
self.mainButtons.append(button)
|
||||
|
||||
def hide_button(self, button):
|
||||
def inner():
|
||||
button.hide()
|
||||
|
||||
return inner
|
||||
|
||||
def fillMainButtons(self):
|
||||
buttons = [
|
||||
('quantity', 'Quantity'),
|
||||
('delete', 'Delete'),
|
||||
('discount', 'Discount - F3'),
|
||||
('modifier', 'Modifier'),
|
||||
('waiter', 'Waiter - F5'),
|
||||
('print_kot', 'Print KOT - F12'),
|
||||
('print_bill', 'Print Bill - F11'),
|
||||
('clear', 'Clear - Esc'),
|
||||
('settle_bill', 'Settle Bill'),
|
||||
('rate', 'Rate'),
|
||||
('move_table', 'Move Table'),
|
||||
('void_bill', 'Void Bill'),
|
||||
('move_kot', 'Move KOT'),
|
||||
('split_bill', 'Split Bill')
|
||||
]
|
||||
for name, text in buttons:
|
||||
self.addMainButton(name, text, self.hide_button)
|
|
@ -0,0 +1,25 @@
|
|||
__author__ = 'tanshu'
|
||||
from PyQt5 import uic, QtCore
|
||||
|
||||
|
||||
file = '/home/tanshu/Programming/summer/summer/QtDesignerFiles/TaxDetail.ui'
|
||||
base, form = uic.loadUiType(file)
|
||||
|
||||
|
||||
class TaxDetail(base, form):
|
||||
def __init__(self, router, tax, parent=None):
|
||||
super(TaxDetail, self).__init__()
|
||||
self.setupUi(self)
|
||||
self.router = router
|
||||
self.tax = tax
|
||||
self.txtName.setText(tax['Name'])
|
||||
self.dsbRate.setMinimum(0)
|
||||
self.dsbRate.setValue(tax['Rate'] * 100)
|
||||
self.accepted.connect(self.save_tax)
|
||||
self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
|
||||
|
||||
def save_tax(self):
|
||||
self.tax['Name'] = self.txtName.text()
|
||||
self.tax['Rate'] = self.dsbRate.value() / 100
|
||||
|
||||
self.router.save_tax(self.tax)
|
|
@ -0,0 +1,74 @@
|
|||
__author__ = 'tanshu'
|
||||
from PyQt5 import uic, QtCore, QtWidgets
|
||||
|
||||
|
||||
file = '/home/tanshu/Programming/summer/summer/QtDesignerFiles/ListForm.ui'
|
||||
base, form = uic.loadUiType(file)
|
||||
|
||||
|
||||
class TaxList(base, form):
|
||||
def __init__(self, router, taxes, parent=None):
|
||||
super(TaxList, self).__init__()
|
||||
self.setupUi(self)
|
||||
self.translateUi()
|
||||
self.router = router
|
||||
self.taxes = taxes
|
||||
self.model = TaxsTableModel(taxes)
|
||||
self.tblItems.setModel(self.model)
|
||||
self.tblItems.doubleClicked.connect(self.show_tax)
|
||||
self.btnAddNew.clicked.connect(self.add_new_tax)
|
||||
self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
|
||||
self.tblItems.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||
|
||||
def translateUi(self):
|
||||
self.setObjectName("TaxList")
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
self.setWindowTitle(_translate("ListForm", "Taxes"))
|
||||
self.btnAddNew.setText(_translate("ListForm", "Add Tax"))
|
||||
|
||||
def update_data(self, data):
|
||||
self.taxes = data
|
||||
self.model = TaxsTableModel(self.taxes)
|
||||
self.tblItems.setModel(self.model)
|
||||
|
||||
def show_tax(self, index):
|
||||
tax = self.model.taxes[index.row()]
|
||||
self.router.show_tax(tax['TaxID'])
|
||||
|
||||
def add_new_tax(self):
|
||||
self.router.show_tax(None)
|
||||
|
||||
|
||||
class TaxsTableModel(QtCore.QAbstractTableModel):
|
||||
def __init__(self, taxes=None, parent=None):
|
||||
QtCore.QAbstractTableModel.__init__(self, parent)
|
||||
self.taxes = taxes if taxes is not None else []
|
||||
|
||||
def rowCount(self, parent):
|
||||
return len(self.taxes)
|
||||
|
||||
def columnCount(self, parent):
|
||||
return 3
|
||||
|
||||
def data(self, index, role):
|
||||
if role == QtCore.Qt.DisplayRole:
|
||||
item = self.taxes[index.row()]
|
||||
column = index.column()
|
||||
if column == 0:
|
||||
return item['Name']
|
||||
elif column == 1:
|
||||
return '{0:,.2f}%'.format(item['Rate'] * 100)
|
||||
elif column == 2:
|
||||
return item['IsFixture']
|
||||
|
||||
def headerData(self, section, orientation, role):
|
||||
if role == QtCore.Qt.DisplayRole:
|
||||
if orientation == QtCore.Qt.Horizontal:
|
||||
if section == 0:
|
||||
return 'Name'
|
||||
elif section == 1:
|
||||
return 'Rate'
|
||||
elif section == 2:
|
||||
return 'Is Fixture?'
|
||||
else:
|
||||
return section + 1
|
|
@ -2,7 +2,7 @@ __author__ = 'tanshu'
|
|||
from PyQt5 import uic, QtCore, QtWidgets
|
||||
|
||||
|
||||
file = '/home/tanshu/Programming/summer/summer/QtDesignerFiles/UserList.ui'
|
||||
file = '/home/tanshu/Programming/summer/summer/QtDesignerFiles/ListForm.ui'
|
||||
base, form = uic.loadUiType(file)
|
||||
|
||||
|
||||
|
@ -10,19 +10,26 @@ class UserList(base, form):
|
|||
def __init__(self, router, users, parent=None):
|
||||
super(UserList, self).__init__()
|
||||
self.setupUi(self)
|
||||
self.translateUi()
|
||||
self.router = router
|
||||
self.users = users
|
||||
self.model = UsersTableModel(users)
|
||||
self.tblUsers.setModel(self.model)
|
||||
self.tblUsers.doubleClicked.connect(self.show_user)
|
||||
self.tblItems.setModel(self.model)
|
||||
self.tblItems.doubleClicked.connect(self.show_user)
|
||||
self.btnAddNew.clicked.connect(self.add_new_user)
|
||||
self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
|
||||
self.tblUsers.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||
self.tblItems.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||
|
||||
def translateUi(self):
|
||||
self.setObjectName("UserList")
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
self.setWindowTitle(_translate("ListForm", "Users"))
|
||||
self.btnAddNew.setText(_translate("ListForm", "Add User"))
|
||||
|
||||
def update_data(self, data):
|
||||
self.users = data
|
||||
self.model = UsersTableModel(self.users)
|
||||
self.tblUsers.setModel(self.model)
|
||||
self.tblItems.setModel(self.model)
|
||||
|
||||
def show_user(self, index):
|
||||
user = self.model.users[index.row()]
|
||||
|
|
|
@ -5,3 +5,7 @@ from summer.templates.UserDetail import UserDetail
|
|||
from summer.templates.UserList import UserList
|
||||
from summer.templates.ProductGroupList import ProductGroupList
|
||||
from summer.templates.ProductGroupDetail import ProductGroupDetail
|
||||
from summer.templates.TaxList import TaxList
|
||||
from summer.templates.TaxDetail import TaxDetail
|
||||
from summer.templates.ProductList import ProductList
|
||||
from summer.templates.ProductDetail import ProductDetail
|
|
@ -1,8 +1,12 @@
|
|||
from summer.templates import RoleDetail, RoleList, UserDetail, UserList, ProductGroupList, ProductGroupDetail
|
||||
from summer.templates import RoleDetail, RoleList, UserDetail, UserList, ProductGroupList, ProductGroupDetail, TaxList, \
|
||||
TaxDetail, ProductList, ProductDetail
|
||||
from summer.templates.SaleWindow import SaleWindow
|
||||
from summer.views.user import show_list as user_list, user_info, save_user, update_user
|
||||
from summer.views.role import show_list as role_list, role_info, save_role, update_role
|
||||
from summer.views.product_group import show_list as product_group_list, product_group_info, save_product_group, \
|
||||
update_product_group
|
||||
from summer.views.tax import show_list as tax_list, tax_info, save_tax, update_tax
|
||||
from summer.views.product import show_list as product_list, product_info, save_product, update_product
|
||||
|
||||
__author__ = 'tanshu'
|
||||
|
||||
|
@ -15,6 +19,11 @@ class Router():
|
|||
self.role_detail_form = None
|
||||
self.product_group_list_form = None
|
||||
self.product_group_detail_form = None
|
||||
self.tax_list_form = None
|
||||
self.tax_detail_form = None
|
||||
self.product_list_form = None
|
||||
self.product_detail_form = None
|
||||
self.sales_form = None
|
||||
|
||||
def show_users(self):
|
||||
users = user_list()
|
||||
|
@ -101,3 +110,73 @@ class Router():
|
|||
save_product_group(product_group)
|
||||
else:
|
||||
update_product_group(product_group)
|
||||
|
||||
|
||||
def show_taxes(self):
|
||||
taxes = tax_list()
|
||||
if self.tax_list_form is None:
|
||||
self.tax_list_form = TaxList(self, taxes)
|
||||
self.tax_list_form.destroyed.connect(self.tax_list_form_destroyed)
|
||||
self.tax_list_form.show()
|
||||
|
||||
def tax_list_form_destroyed(self):
|
||||
self.tax_list_form = None
|
||||
|
||||
def show_tax(self, id=None):
|
||||
tax = tax_info(id)
|
||||
if self.tax_detail_form is None:
|
||||
self.tax_detail_form = TaxDetail(self, tax)
|
||||
self.tax_detail_form.destroyed.connect(self.tax_detail_form_destroyed)
|
||||
self.tax_detail_form.show()
|
||||
|
||||
def tax_detail_form_destroyed(self):
|
||||
self.tax_detail_form = None
|
||||
if self.tax_list_form is not None:
|
||||
self.tax_list_form.update_data(tax_list())
|
||||
|
||||
def save_tax(self, tax):
|
||||
if 'TaxID' not in tax:
|
||||
save_tax(tax)
|
||||
else:
|
||||
update_tax(tax)
|
||||
|
||||
|
||||
def show_products(self):
|
||||
products = product_list()
|
||||
if self.product_list_form is None:
|
||||
self.product_list_form = ProductList(self, products)
|
||||
self.product_list_form.destroyed.connect(self.product_list_form_destroyed)
|
||||
self.product_list_form.show()
|
||||
|
||||
def product_list_form_destroyed(self):
|
||||
self.product_list_form = None
|
||||
|
||||
def show_product(self, id=None):
|
||||
pass
|
||||
product = product_info(id)
|
||||
product_group = product_group_list()
|
||||
taxes = tax_list()
|
||||
if self.product_detail_form is None:
|
||||
self.product_detail_form = ProductDetail(self, product, product_group, taxes)
|
||||
self.product_detail_form.destroyed.connect(self.product_detail_form_destroyed)
|
||||
self.product_detail_form.show()
|
||||
|
||||
def product_detail_form_destroyed(self):
|
||||
self.product_detail_form = None
|
||||
if self.product_list_form is not None:
|
||||
self.product_list_form.update_data(product_list())
|
||||
|
||||
def save_product(self, product):
|
||||
if 'ProductID' not in product:
|
||||
save_product(product)
|
||||
else:
|
||||
update_product(product)
|
||||
|
||||
def show_sales(self):
|
||||
if self.sales_form is None:
|
||||
self.sales_form = SaleWindow(self)
|
||||
self.sales_form.destroyed.connect(self.sales_form_destroyed)
|
||||
self.sales_form.show()
|
||||
|
||||
def sales_form_destroyed(self):
|
||||
self.sales_form = None
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
__author__ = 'tanshu'
|
||||
from decimal import Decimal, InvalidOperation
|
||||
|
||||
from summer.models import session_scope
|
||||
from summer.models.validation_exception import ValidationError
|
||||
from summer.models.master import Product
|
||||
|
||||
|
||||
def save_product(json):
|
||||
name = json['Name'].strip()
|
||||
if name == '':
|
||||
raise ValidationError('Name cannot be blank')
|
||||
|
||||
units = json['Units'].strip()
|
||||
product_group = json['ProductGroup']
|
||||
if product_group is None:
|
||||
raise ValidationError('Please choose a product group')
|
||||
product_group_id = product_group['ProductGroupID']
|
||||
|
||||
try:
|
||||
price = Decimal(json['Price'])
|
||||
if price < 0:
|
||||
raise ValidationError("Price must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Price must be a decimal >= 0")
|
||||
|
||||
has_happy_hour = json['HasHappyHour']
|
||||
|
||||
service_tax = json['ServiceTax']
|
||||
if service_tax is None:
|
||||
raise ValidationError('Please choose a service tax')
|
||||
service_tax_id = service_tax['TaxID']
|
||||
|
||||
vat = json['Vat']
|
||||
if vat is None:
|
||||
raise ValidationError('Please choose vat')
|
||||
vat_id = vat['TaxID']
|
||||
|
||||
try:
|
||||
service_charge = Decimal(json['ServiceCharge'])
|
||||
if service_charge < 0:
|
||||
raise ValidationError("Service Charge must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Service Charge must be a decimal >= 0")
|
||||
|
||||
sc_taxable = json['ScTaxable']
|
||||
is_active = json['IsActive']
|
||||
try:
|
||||
sort_order = Decimal(json['SortOrder'])
|
||||
if sort_order < 0:
|
||||
raise ValidationError("Sort Order must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Sort Order must be a decimal >= 0")
|
||||
|
||||
item = Product(name, units, product_group_id, price, has_happy_hour, service_tax_id, vat_id, service_charge,
|
||||
sc_taxable, is_active, sort_order)
|
||||
with session_scope() as DBSession:
|
||||
DBSession.add(item)
|
||||
return product_info(item.id)
|
||||
|
||||
|
||||
def update_product(json):
|
||||
with session_scope() as DBSession:
|
||||
item = Product.by_id(json['ProductID'], session=DBSession)
|
||||
if item.is_fixture:
|
||||
raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.full_name))
|
||||
item.name = json['Name'].strip()
|
||||
item.units = json['Units'].strip()
|
||||
item.product_group_id = json['ProductGroup']['ProductGroupID']
|
||||
try:
|
||||
item.price = Decimal(json['Price'])
|
||||
if item.price < 0:
|
||||
raise ValidationError("Price must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Price must be a decimal >= 0")
|
||||
item.has_happy_hour = json['HasHappyHour']
|
||||
item.service_tax_id = json['ServiceTax']['TaxID']
|
||||
item.vat_id = json['Vat']['TaxID']
|
||||
try:
|
||||
item.service_charge = Decimal(json['ServiceCharge'])
|
||||
if item.service_charge <= 0:
|
||||
raise ValidationError("Service Charge must be a decimal > 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Service Charge must be a decimal > 0")
|
||||
item.sc_taxable = json['ScTaxable']
|
||||
item.is_active = json['IsActive']
|
||||
try:
|
||||
item.sort_order = Decimal(json['SortOrder'])
|
||||
if item.sort_order < 0:
|
||||
raise ValidationError("Sort Order must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Sort Order must be a decimal >= 0")
|
||||
return product_info(item.id)
|
||||
|
||||
|
||||
def delete_product(id):
|
||||
with session_scope() as DBSession:
|
||||
item = Product.by_id(id, session=DBSession)
|
||||
# TODO: Proper advanced delete checking
|
||||
# 'Advanced Delete'
|
||||
advance_delete = True
|
||||
can_delete, reason = item.can_delete(advance_delete)
|
||||
|
||||
if can_delete:
|
||||
delete_with_data(item, DBSession)
|
||||
return product_info(None)
|
||||
else:
|
||||
raise ValidationError("Cannot delete product because {0}".format(reason))
|
||||
|
||||
|
||||
def show_list():
|
||||
with session_scope() as DBSession:
|
||||
list = DBSession.query(Product).order_by(Product.sort_order).order_by(Product.name).all()
|
||||
products = []
|
||||
for item in list:
|
||||
products.append({'Name': item.name, 'Units': item.units, 'ProductGroup': {'Name': item.product_group.name},
|
||||
'Price': item.price, 'HasHappyHour': item.has_happy_hour,
|
||||
'ServiceTax': {'Name': item.service_tax.name, 'Rate': item.service_tax.rate},
|
||||
'Vat': {'Name': item.vat.name, 'Rate': item.vat.rate},
|
||||
'ServiceCharge': item.service_charge, 'ScTaxable': item.sc_taxable,
|
||||
'IsActive': item.is_active, 'IsFixture': item.is_fixture, 'SortOrder': item.sort_order})
|
||||
return products
|
||||
|
||||
|
||||
def product_info(id):
|
||||
with session_scope() as DBSession:
|
||||
if id is None:
|
||||
item = {'Name': '', 'Units': '', 'ProductGroup': {'ProductGroupID': None}, 'Price': 0,
|
||||
'HasHappyHour': False, 'ServiceTax': {'TaxID': None}, 'Vat': {'TaxID': None}, 'ServiceCharge': 0,
|
||||
'ScTaxable': True, 'IsActive': True, 'IsFixture': False, 'SortOrder': 0}
|
||||
else:
|
||||
product = Product.by_id(id, session=DBSession)
|
||||
item = {'ProductID': product.id, 'Name': product.name, 'Units': product.units,
|
||||
'ProductGroup': {'ProductGroupID': product.product_group.id, 'Name': product.product_group.name},
|
||||
'Price': product.price, 'HasHappyHour': product.has_happy_hour,
|
||||
'ServiceTax': {'TaxID': product.service_tax.id, 'Name': product.service_tax.name,
|
||||
'Rate': product.service_tax.rate},
|
||||
'Vat': {'TaxID': product.vat.id, 'Name': product.vat.name, 'Rate': product.vat.rate},
|
||||
'ServiceCharge': product.service_charge, 'ScTaxable': product.sc_taxable,
|
||||
'IsActive': product.is_active, 'IsFixture': product.is_fixture, 'SortOrder': product.sort_order}
|
||||
return item
|
||||
|
||||
|
||||
def delete_with_data(product, *, session=None):
|
||||
pass
|
||||
# suspense_product = Product.by_id(Product.suspense(), session=session)
|
||||
# query = Voucher.query().options(joinedload_all(Voucher.inventories, Inventory.product, innerjoin=True)) \
|
||||
# .filter(Voucher.inventories.any(Inventory.product_id == product.id)) \
|
||||
# .all()
|
||||
#
|
||||
# for voucher in query:
|
||||
# others, sus_inv, prod_inv = False, None, None
|
||||
# for inventory in voucher.inventories:
|
||||
# if inventory.product_id == product.id:
|
||||
# prod_inv = inventory
|
||||
# elif inventory.product_id == Product.suspense():
|
||||
# sus_inv = inventory
|
||||
# else:
|
||||
# others = True
|
||||
# if not others and voucher.type == VoucherType.by_id('Issue'):
|
||||
# DBSession.delete(voucher)
|
||||
# else:
|
||||
# if sus_inv is None:
|
||||
# prod_inv.product = suspense_product
|
||||
# prod_inv.quantity = prod_inv.amount
|
||||
# prod_inv.rate = 1
|
||||
# prod_inv.tax = 0
|
||||
# prod_inv.discount = 0
|
||||
# prod_inv.batch = suspense_batch
|
||||
# voucher.narration += '\nSuspense \u20B9{0:,.2f} is {1}'.format(prod_inv.amount, product.name)
|
||||
# else:
|
||||
# sus_inv.quantity += prod_inv.amount
|
||||
# DBSession.delete(prod_inv)
|
||||
# voucher.narration += '\nDeleted \u20B9{0:,.2f} of {1}'.format(prod_inv.amount, product.name)
|
||||
# for batch in product.batches:
|
||||
# DBSession.delete(batch)
|
||||
# DBSession.delete(product)
|
|
@ -0,0 +1,59 @@
|
|||
from decimal import Decimal, InvalidOperation
|
||||
|
||||
from summer.models import session_scope
|
||||
from summer.models.validation_exception import ValidationError
|
||||
|
||||
|
||||
__author__ = 'tanshu'
|
||||
|
||||
from summer.models.master import Tax
|
||||
|
||||
|
||||
def save_tax(json):
|
||||
name = json['Name'].strip()
|
||||
try:
|
||||
rate = Decimal(json['Rate'])
|
||||
if rate < 0:
|
||||
raise ValidationError("Rate must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Rate must be a decimal >= 0")
|
||||
item = Tax(name, rate)
|
||||
with session_scope() as DBSession:
|
||||
DBSession.add(item)
|
||||
return tax_info(item.id)
|
||||
|
||||
|
||||
def update_tax(json):
|
||||
with session_scope() as DBSession:
|
||||
item = Tax.by_id(json['TaxID'], session=DBSession)
|
||||
if item.is_fixture:
|
||||
raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.name))
|
||||
item.name = json['Name'].strip()
|
||||
try:
|
||||
rate = Decimal(json['Rate'])
|
||||
if rate < 0:
|
||||
raise ValidationError("Rate must be a decimal >= 0")
|
||||
except (ValueError, InvalidOperation):
|
||||
raise ValidationError("Rate must be a decimal >= 0")
|
||||
item.rate = rate
|
||||
return tax_info(item.id)
|
||||
|
||||
|
||||
def show_list():
|
||||
with session_scope() as DBSession:
|
||||
list = DBSession.query(Tax).order_by(Tax.name)
|
||||
taxes = []
|
||||
for item in list:
|
||||
taxes.append({'TaxID': item.id, 'Name': item.name, 'Rate': item.rate, 'IsFixture': item.is_fixture})
|
||||
return taxes
|
||||
|
||||
|
||||
def tax_info(id):
|
||||
with session_scope() as DBSession:
|
||||
if id is None:
|
||||
item = {'Name': '', 'Rate': 0, 'IsFixture': False}
|
||||
else:
|
||||
tax = Tax.by_id(id, session=DBSession)
|
||||
return {'TaxID': tax.id, 'Name': tax.name, 'Rate': tax.rate, 'IsFixture': tax.is_fixture}
|
||||
return item
|
||||
|
Loading…
Reference in New Issue