Feature: Product Group Templates / Views created and wired up.

Chore: Refactored importing into view from templates
This commit is contained in:
Amritanshu 2014-07-02 00:41:04 +05:30
parent d88db662f6
commit d44daf921b
12 changed files with 416 additions and 18 deletions

View File

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProductGroupDetails</class>
<widget class="QDialog" name="ProductGroupDetails">
<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>Product Group 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>Maximum Discount</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="sbMaxDiscount"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Header</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="txtHeader">
<property name="inputMask">
<string notr="true"/>
</property>
<property name="echoMode">
<enum>QLineEdit::Normal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Sort Order</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="sbSortOrder"/>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="chkIsActive">
<property name="text">
<string>Is Active?</string>
</property>
</widget>
</item>
<item row="8" 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>sbMaxDiscount</tabstop>
<tabstop>txtHeader</tabstop>
<tabstop>sbSortOrder</tabstop>
<tabstop>chkIsActive</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ProductGroupDetails</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>ProductGroupDetails</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>

View File

@ -0,0 +1,37 @@
<?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>

View File

@ -32,7 +32,7 @@ def initialize_sql(engine):
def schema_exists(engine): def schema_exists(engine):
from models.master import DbSetting from summer.models.master import DbSetting
with engine.connect() as connection: with engine.connect() as connection:
return engine.dialect.has_table(connection, DbSetting.__tablename__) return engine.dialect.has_table(connection, DbSetting.__tablename__)

View File

@ -12,12 +12,11 @@ class Product(Base):
__tableagrs__ = (UniqueConstraint('name', 'units')) __tableagrs__ = (UniqueConstraint('name', 'units'))
id = Column('product_id', GUID(), primary_key=True, default=uuid.uuid4) id = Column('product_id', GUID(), primary_key=True, default=uuid.uuid4)
code = Column('code', Integer, unique=True, nullable=False)
name = Column('name', Unicode(255), nullable=False) name = Column('name', Unicode(255), nullable=False)
units = Column('units', Unicode(255), nullable=False) units = Column('units', Unicode(255), nullable=False)
product_group_id = Column('product_group_id', GUID(), ForeignKey('product_groups.product_group_id'), nullable=False) product_group_id = Column('product_group_id', GUID(), ForeignKey('product_groups.product_group_id'), nullable=False)
price = Column('price', Numeric, nullable=False) price = Column('price', Numeric, nullable=False)
happy_hour = Column('happy_hour', Boolean, nullable=False) has_happy_hour = Column('has_happy_hour', Boolean, nullable=False)
service_tax_id = Column('service_tax_id', GUID(), ForeignKey('taxes.tax_id'), nullable=False) service_tax_id = Column('service_tax_id', GUID(), ForeignKey('taxes.tax_id'), nullable=False)
vat_id = Column('vat_id', GUID(), ForeignKey('taxes.tax_id'), nullable=False) vat_id = Column('vat_id', GUID(), ForeignKey('taxes.tax_id'), nullable=False)
@ -127,14 +126,10 @@ class ProductGroup(Base):
self.is_fixture = is_fixture self.is_fixture = is_fixture
@classmethod @classmethod
def list(cls): def by_id(cls, id, * , session=None):
return DBSession.query(cls).order_by(cls.name)
@classmethod
def by_id(cls, id):
if not isinstance(id, uuid.UUID): if not isinstance(id, uuid.UUID):
id = uuid.UUID(id) id = uuid.UUID(id)
return DBSession.query(cls).filter(cls.id == id).first() return session.query(cls).filter(cls.id == id).first()
def can_delete(self, advanced_delete): def can_delete(self, advanced_delete):
if self.is_fixture: if self.is_fixture:

View File

@ -15,6 +15,7 @@ class MainWindow(base, form):
self.btnExit.clicked.connect(self.handle_exit) self.btnExit.clicked.connect(self.handle_exit)
self.btnUsers.clicked.connect(router.show_users) self.btnUsers.clicked.connect(router.show_users)
self.btnRoles.clicked.connect(router.show_roles) self.btnRoles.clicked.connect(router.show_roles)
self.btnProductGroups.clicked.connect(router.show_product_groups)
def handle_exit(self): def handle_exit(self):
self.close() self.close()

View File

@ -0,0 +1,33 @@
__author__ = 'tanshu'
from PyQt5 import uic, QtCore
file = '/home/tanshu/Programming/summer/summer/QtDesignerFiles/ProductGroupDetail.ui'
base, form = uic.loadUiType(file)
class ProductGroupDetail(base, form):
def __init__(self, router, product_group, parent=None):
super(ProductGroupDetail, self).__init__()
self.setupUi(self)
self.router = router
self.product_group = product_group
self.txtName.setText(product_group['Name'])
self.sbMaxDiscount.setMaximum(100)
self.sbMaxDiscount.setMinimum(0)
self.sbMaxDiscount.setValue(product_group['MaxDiscount'] * 100)
self.txtHeader.setText(product_group['Header'])
self.chkIsActive.setCheckState(QtCore.Qt.Checked if product_group['IsActive'] else QtCore.Qt.Unchecked)
self.sbSortOrder.setMinimum(0)
self.sbSortOrder.setValue(product_group['SortOrder'])
self.accepted.connect(self.save_product_group)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
def save_product_group(self):
self.product_group['Name'] = self.txtName.text()
self.product_group['MaxDiscount'] = self.sbMaxDiscount.value() / 100
self.product_group['Header'] = self.txtHeader.text()
self.product_group['IsActive'] = self.chkIsActive.isChecked()
self.product_group['SortOrder'] = self.sbSortOrder.value()
self.router.save_product_group(self.product_group)

View File

@ -0,0 +1,79 @@
__author__ = 'tanshu'
from PyQt5 import uic, QtCore, QtWidgets
file = '/home/tanshu/Programming/summer/summer/QtDesignerFiles/ProductGroupList.ui'
base, form = uic.loadUiType(file)
class ProductGroupList(base, form):
def __init__(self, router, product_groups, parent=None):
super(ProductGroupList, self).__init__()
self.setupUi(self)
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.btnAddNew.clicked.connect(self.add_new_product_group)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
self.tblProductGroups.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
def update_data(self, data):
self.product_groups = data
self.model = ProductGroupsTableModel(self.product_groups)
self.tblProductGroups.setModel(self.model)
def show_product_group(self, index):
product_group = self.model.product_groups[index.row()]
self.router.show_product_group(product_group['ProductGroupID'])
def add_new_product_group(self):
self.router.show_product_group(None)
class ProductGroupsTableModel(QtCore.QAbstractTableModel):
def __init__(self, product_groups=None, parent=None):
QtCore.QAbstractTableModel.__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 columnCount(self, parent):
return 6
def data(self, index, role):
if role == QtCore.Qt.DisplayRole:
item = self.product_groups[index.row()]
column = index.column()
if column == 0:
return item['Name']
elif column == 1:
return '{0:,.2f}%'.format(item['MaxDiscount'] * 100)
elif column == 2:
return item['Header']
elif column == 3:
return item['IsActive']
elif column == 4:
return item['IsFixture']
elif column == 5:
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 'Maximum Discount'
elif section == 2:
return 'Header'
elif section == 3:
return 'Is Active?'
elif section == 4:
return 'Is Fixture?'
elif section == 5:
return 'Sort Order'
else:
return section + 1

View File

@ -0,0 +1,7 @@
__author__ = 'tanshu'
from summer.templates.RoleDetail import RoleDetail
from summer.templates.RoleList import RoleList
from summer.templates.UserDetail import UserDetail
from summer.templates.UserList import UserList
from summer.templates.ProductGroupList import ProductGroupList
from summer.templates.ProductGroupDetail import ProductGroupDetail

View File

@ -1,9 +1,8 @@
from summer.templates.RoleDetail import RoleDetail from summer.templates import RoleDetail, RoleList, UserDetail, UserList, ProductGroupList, ProductGroupDetail
from summer.templates.RoleList import RoleList
from summer.templates.UserDetail import UserDetail
from summer.templates.UserList import UserList
from summer.views.user import show_list as user_list, user_info, save_user, update_user 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.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
__author__ = 'tanshu' __author__ = 'tanshu'
@ -14,6 +13,8 @@ class Router():
self.user_detail_form = None self.user_detail_form = None
self.role_list_form = None self.role_list_form = None
self.role_detail_form = None self.role_detail_form = None
self.product_group_list_form = None
self.product_group_detail_form = None
def show_users(self): def show_users(self):
users = user_list() users = user_list()
@ -71,3 +72,32 @@ class Router():
save_role(role) save_role(role)
else: else:
update_role(role) update_role(role)
def show_product_groups(self):
product_groups = product_group_list()
if self.product_group_list_form is None:
self.product_group_list_form = ProductGroupList(self, product_groups)
self.product_group_list_form.destroyed.connect(self.product_group_list_form_destroyed)
self.product_group_list_form.show()
def product_group_list_form_destroyed(self):
self.product_group_list_form = None
def show_product_group(self, id=None):
product_group = product_group_info(id)
if self.product_group_detail_form is None:
self.product_group_detail_form = ProductGroupDetail(self, product_group)
self.product_group_detail_form.destroyed.connect(self.product_group_detail_form_destroyed)
self.product_group_detail_form.show()
def product_group_detail_form_destroyed(self):
self.product_group_detail_form = None
if self.product_group_list_form is not None:
self.product_group_list_form.update_data(product_group_list())
def save_product_group(self, product_group):
if 'ProductGroupID' not in product_group:
save_product_group(product_group)
else:
update_product_group(product_group)

View File

@ -0,0 +1,81 @@
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 ProductGroup
def save_product_group(json):
name = json['Name'].strip()
try:
max_discount = Decimal(json['MaxDiscount'])
if max_discount < 0 or max_discount > 1:
raise ValidationError("Fraction must be a decimal >= 0 <= 1")
except (ValueError, InvalidOperation):
raise ValidationError("Fraction must be a decimal >= 0 <= 1")
header = json['Header'].strip()
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")
is_active = json['IsActive']
item = ProductGroup(name, max_discount, header, sort_order, is_active)
with session_scope() as DBSession:
DBSession.add(item)
return product_group_info(item.id)
def update_product_group(json):
with session_scope() as DBSession:
item = ProductGroup.by_id(json['ProductGroupID'], 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:
max_discount = Decimal(json['MaxDiscount'])
if max_discount < 0 or max_discount > 1:
raise ValidationError("Fraction must be a decimal >= 0 <= 1")
except (ValueError, InvalidOperation):
raise ValidationError("Fraction must be a decimal >= 0 <= 1")
item.max_discount = max_discount
item.header = json['Header'].strip()
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.sort_order = sort_order
item.is_active = json['IsActive']
return product_group_info(item.id)
def show_list():
with session_scope() as DBSession:
list = DBSession.query(ProductGroup).order_by(ProductGroup.sort_order).order_by(ProductGroup.name)
product_groups = []
for item in list:
product_groups.append(
{'ProductGroupID': item.id, 'Name': item.name, 'MaxDiscount': item.max_discount, 'Header': item.header,
'IsActive': item.is_active, 'IsFixture': item.is_fixture, 'SortOrder': item.sort_order})
return product_groups
def product_group_info(id):
with session_scope() as DBSession:
if id is None:
item = {'Name': '', 'MaxDiscount': 1, 'Header': '', 'IsActive': True, 'IsFixture': False, 'SortOrder': 0}
else:
product_group = ProductGroup.by_id(id, session=DBSession)
return {'ProductGroupID': product_group.id, 'Name': product_group.name,
'MaxDiscount': product_group.max_discount, 'Header': product_group.header,
'IsActive': product_group.is_active, 'IsFixture': product_group.is_fixture,
'SortOrder': product_group.sort_order}
return item

View File

@ -6,7 +6,7 @@ from summer.models.auth import Role, Permission
def save_role(json): def save_role(json):
role = Role(json['Name']) role = Role(json['Name'].strip())
with session_scope() as DBSession: with session_scope() as DBSession:
DBSession.add(role) DBSession.add(role)
add_permissions(role, json['Permissions'], DBSession) add_permissions(role, json['Permissions'], DBSession)
@ -16,7 +16,7 @@ def save_role(json):
def update_role(json): def update_role(json):
with session_scope() as DBSession: with session_scope() as DBSession:
role = Role.by_id(json['RoleID'], session=DBSession) role = Role.by_id(json['RoleID'], session=DBSession)
role.name = json['Name'] role.name = json['Name'].strip()
add_permissions(role, json['Permissions'], session=DBSession) add_permissions(role, json['Permissions'], session=DBSession)
return role_info(role.id) return role_info(role.id)

View File

@ -4,7 +4,7 @@ from summer.models.validation_exception import ValidationError
def save_user(json): def save_user(json):
user = User(json['Name'], json['Password'], json['LockedOut']) user = User(json['Name'].strip(), json['Password'], json['LockedOut'])
with session_scope() as DBSession: with session_scope() as DBSession:
DBSession.add(user) DBSession.add(user)
add_roles(user, json['Roles'], session=DBSession) add_roles(user, json['Roles'], session=DBSession)
@ -15,10 +15,10 @@ def update_user(json):
with session_scope() as DBSession: with session_scope() as DBSession:
user = User.by_id(json['UserID'], session=DBSession) user = User.by_id(json['UserID'], session=DBSession)
if user is None: if user is None:
raise ValidationError('User name / id not found') raise ValidationError('User not found')
has_permission = True has_permission = True
if has_permission: if has_permission:
user.name = json['Name'] user.name = json['Name'].strip()
user.locked_out = json['LockedOut'] user.locked_out = json['LockedOut']
add_roles(user, json['Roles'], session=DBSession) add_roles(user, json['Roles'], session=DBSession)