Compare commits
14 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7249598b35 | ||
![]() |
3514b47776 | ||
![]() |
494cae2433 | ||
![]() |
06d1ada3fd | ||
![]() |
827927355d | ||
![]() |
6a26de3622 | ||
![]() |
5e60a9e0af | ||
![]() |
1c5e3296d7 | ||
![]() |
25d1eaa816 | ||
![]() |
a7ff4e4ffc | ||
![]() |
4a3f4cf829 | ||
![]() |
af7deee26b | ||
![]() |
4bb35b50f4 | ||
![]() |
eae58f97ad |
26
CHANGELOG.md
26
CHANGELOG.md
|
@ -5,6 +5,32 @@ All notable changes to tailbone-corepos will be documented in this file.
|
|||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## v0.3.2 (2024-11-18)
|
||||
|
||||
### Fix
|
||||
|
||||
- add startup workaround for CORE model imports, to avoid error
|
||||
|
||||
## v0.3.1 (2024-08-18)
|
||||
|
||||
### Fix
|
||||
|
||||
- refactory grid usage per wuttaweb
|
||||
|
||||
## v0.3.0 (2024-08-06)
|
||||
|
||||
### Feat
|
||||
|
||||
- add view for CORE Custom Receipt Lines (`op.customReceipt`)
|
||||
|
||||
## v0.2.1 (2024-07-05)
|
||||
|
||||
### Fix
|
||||
|
||||
- add link to CORE for profile employee tab
|
||||
- link to CORE when viewing profile member tab
|
||||
- remove dependency for `six` package
|
||||
|
||||
## v0.2.0 (2024-06-10)
|
||||
|
||||
### Feat
|
||||
|
|
12
README.md
Normal file
12
README.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
# tailbone-corepos
|
||||
|
||||
Rattail is a retail software framework, released under the GNU General
|
||||
Public License.
|
||||
|
||||
This package contains software interfaces for the [CORE
|
||||
POS](https://www.core-pos.com/) system, which is open source and
|
||||
freely available.
|
||||
|
||||
Please see Rattail's [home page](https://rattailproject.org/) for more
|
||||
information.
|
15
README.rst
15
README.rst
|
@ -1,15 +0,0 @@
|
|||
|
||||
tailbone-corepos
|
||||
================
|
||||
|
||||
Rattail is a retail software framework, released under the GNU General Public
|
||||
License.
|
||||
|
||||
This package contains software interfaces for the `CORE POS`_ system, which is
|
||||
open source and freely available.
|
||||
|
||||
.. _`CORE POS`: https://www.core-pos.com/
|
||||
|
||||
Please see Rattail's `home page`_ for more information.
|
||||
|
||||
.. _`home page`: https://rattailproject.org/
|
|
@ -6,9 +6,9 @@ build-backend = "hatchling.build"
|
|||
|
||||
[project]
|
||||
name = "tailbone-corepos"
|
||||
version = "0.2.0"
|
||||
version = "0.3.2"
|
||||
description = "Tailbone interfaces for CORE POS"
|
||||
readme = "README.rst"
|
||||
readme = "README.md"
|
||||
authors = [{name = "Lance Edgar", email = "lance@edbob.org"}]
|
||||
license = {text = "GNU GPL v3+"}
|
||||
classifiers = [
|
||||
|
@ -28,16 +28,15 @@ classifiers = [
|
|||
dependencies = [
|
||||
"rattail",
|
||||
"rattail-corepos",
|
||||
"six",
|
||||
"Tailbone",
|
||||
]
|
||||
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://redmine.rattailproject.org/projects/corepos-integration"
|
||||
Repository = "https://kallithea.rattailproject.org/rattail-project/tailbone-corepos"
|
||||
Issues = "https://redmine.rattailproject.org/projects/corepos-integration/issues"
|
||||
Changelog = "https://kallithea.rattailproject.org/rattail-project/tailbone-corepos/files/master/CHANGELOG.md"
|
||||
Homepage = "https://rattailproject.org"
|
||||
Repository = "https://forgejo.wuttaproject.org/rattail/tailbone-corepos"
|
||||
Issues = "https://forgejo.wuttaproject.org/rattail/tailbone-corepos/issues"
|
||||
Changelog = "https://forgejo.wuttaproject.org/rattail/tailbone-corepos/src/branch/master/CHANGELOG.md"
|
||||
|
||||
|
||||
[project.entry-points."tailbone.providers"]
|
||||
|
|
|
@ -71,6 +71,11 @@ def make_corepos_menu(request):
|
|||
'route': 'corepos.member_types',
|
||||
'perm': 'corepos.member_types.list',
|
||||
},
|
||||
{
|
||||
'title': "Member Contact Preferences",
|
||||
'route': 'corepos.member_contact_prefs',
|
||||
'perm': 'corepos.member_contact_prefs.list',
|
||||
},
|
||||
{
|
||||
'title': "Employees",
|
||||
'route': 'corepos.employees',
|
||||
|
@ -202,6 +207,11 @@ def make_corepos_menu(request):
|
|||
'route': 'corepos.tenders',
|
||||
'perm': 'corepos.tenders.list',
|
||||
},
|
||||
{
|
||||
'title': "Custom Receipt Lines",
|
||||
'route': 'corepos.custom_receipt_lines',
|
||||
'perm': 'corepos.custom_receipt_lines.list',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2023 Lance Edgar
|
||||
# Copyright © 2010-2024 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -24,6 +24,7 @@
|
|||
Tailbone Provider for CORE-POS Integration
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.orm import sessionmaker, scoped_session
|
||||
from zope.sqlalchemy import register
|
||||
|
||||
|
@ -71,6 +72,37 @@ class TailboneCorePosProvider(TailboneProvider):
|
|||
register(Session)
|
||||
ExtraCoreTransArchiveSessions[key] = Session
|
||||
|
||||
# must import all sqlalchemy models before things get rolling,
|
||||
# otherwise can have errors about continuum TransactionMeta class
|
||||
# not yet mapped, when relevant pages are first requested...
|
||||
# cf. https://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/database/sqlalchemy.html#importing-all-sqlalchemy-models
|
||||
# hat tip to https://stackoverflow.com/a/59241485
|
||||
if rattail_config.core_office_op_engine:
|
||||
app = rattail_config.get_app()
|
||||
corepos = app.get_corepos_handler()
|
||||
|
||||
# nb. use fake db to avoid true cxn errors, since the only
|
||||
# point of this is to load the models
|
||||
engine = sa.create_engine('sqlite://')
|
||||
|
||||
# office_op
|
||||
core_model = corepos.get_model_office_op()
|
||||
core_session = corepos.make_session_office_op(bind=engine)
|
||||
try:
|
||||
core_session.query(core_model.Store).first()
|
||||
except sa.exc.OperationalError:
|
||||
pass
|
||||
core_session.close()
|
||||
|
||||
# office_trans
|
||||
core_model = corepos.get_model_office_trans()
|
||||
core_session = corepos.make_session_office_trans(bind=engine)
|
||||
try:
|
||||
core_session.query(core_model.TransactionDetail).first()
|
||||
except sa.exc.OperationalError:
|
||||
pass
|
||||
core_session.close()
|
||||
|
||||
def get_provided_views(self):
|
||||
return {
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2023 Lance Edgar
|
||||
# Copyright © 2010-2024 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -48,6 +48,7 @@ def defaults(config, **kwargs):
|
|||
config.include(mod('tailbone_corepos.views.corepos.customers'))
|
||||
config.include(mod('tailbone_corepos.views.corepos.employees'))
|
||||
config.include(mod('tailbone_corepos.views.corepos.coupons'))
|
||||
config.include(mod('tailbone_corepos.views.corepos.receipts'))
|
||||
config.include(mod('tailbone_corepos.views.corepos.tenders'))
|
||||
config.include(mod('tailbone_corepos.views.corepos.stockpurchases'))
|
||||
config.include(mod('tailbone_corepos.views.corepos.taxrates'))
|
||||
|
|
|
@ -125,7 +125,8 @@ class UserGroupView(CoreOfficeMasterView):
|
|||
permission_prefix = self.get_permission_prefix()
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
key='{}.users'.format(route_prefix),
|
||||
self.request,
|
||||
key=f'{route_prefix}.users',
|
||||
data=[],
|
||||
columns=[
|
||||
'username',
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2023 Lance Edgar
|
||||
# Copyright © 2010-2024 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -26,8 +26,8 @@ CORE-POS member views
|
|||
|
||||
from sqlalchemy import orm
|
||||
|
||||
from corepos.db.office_op import model as corepos
|
||||
from corepos.db.office_trans import model as coretrans
|
||||
from corepos.db.office_op.model import MemberType, MemberContactPreference, MemberInfo
|
||||
from corepos.db.office_trans.model import StockPurchase
|
||||
|
||||
from webhelpers2.html import HTML, tags
|
||||
|
||||
|
@ -39,7 +39,7 @@ class MemberTypeView(CoreOfficeMasterView):
|
|||
"""
|
||||
Master view for member types
|
||||
"""
|
||||
model_class = corepos.MemberType
|
||||
model_class = MemberType
|
||||
model_title = "CORE-POS Member Type"
|
||||
url_prefix = '/core-pos/member-types'
|
||||
route_prefix = 'corepos.member_types'
|
||||
|
@ -56,11 +56,29 @@ class MemberTypeView(CoreOfficeMasterView):
|
|||
g.set_link('description')
|
||||
|
||||
|
||||
class MemberContactPreferenceView(CoreOfficeMasterView):
|
||||
"""
|
||||
Master view for member contact preferences
|
||||
"""
|
||||
model_class = MemberContactPreference
|
||||
model_title = "CORE-POS Member Contact Preference"
|
||||
url_prefix = '/core-pos/member-contact-prefs'
|
||||
route_prefix = 'corepos.member_contact_prefs'
|
||||
|
||||
def configure_grid(self, g):
|
||||
super().configure_grid(g)
|
||||
|
||||
g.set_sort_defaults('id')
|
||||
g.set_link('id')
|
||||
|
||||
g.set_link('description')
|
||||
|
||||
|
||||
class MemberView(CoreOfficeMasterView):
|
||||
"""
|
||||
Master view for members
|
||||
"""
|
||||
model_class = corepos.MemberInfo
|
||||
model_class = MemberInfo
|
||||
model_title = "CORE-POS Member (classic)"
|
||||
model_title_plural = "CORE-POS Members (classic)"
|
||||
url_prefix = '/core-pos/members'
|
||||
|
@ -107,7 +125,7 @@ class MemberView(CoreOfficeMasterView):
|
|||
]
|
||||
|
||||
has_rows = True
|
||||
model_row_class = coretrans.StockPurchase
|
||||
model_row_class = StockPurchase
|
||||
rows_title = "Stock Purchases"
|
||||
|
||||
row_labels = {
|
||||
|
@ -196,6 +214,9 @@ class MemberView(CoreOfficeMasterView):
|
|||
return tags.link_to(text, url)
|
||||
|
||||
def render_equity_live_balance(self, member, field):
|
||||
app = self.get_rattail_app()
|
||||
corepos = app.get_corepos_handler()
|
||||
coretrans = corepos.get_model_office_trans()
|
||||
try:
|
||||
balance = CoreTransSession.query(coretrans.EquityLiveBalance)\
|
||||
.filter(coretrans.EquityLiveBalance.member_number == member.card_number)\
|
||||
|
@ -214,11 +235,14 @@ class MemberView(CoreOfficeMasterView):
|
|||
return [self.make_xref_button(url=url, text="View in CORE Office")]
|
||||
|
||||
def get_row_data(self, member):
|
||||
app = self.get_rattail_app()
|
||||
corepos = app.get_corepos_handler()
|
||||
coretrans = corepos.get_model_office_trans()
|
||||
return CoreTransSession.query(coretrans.StockPurchase)\
|
||||
.filter(coretrans.StockPurchase.card_number == member.card_number)
|
||||
|
||||
def get_parent(self, stock_purchase):
|
||||
return self.Session.get(corepos.MemberInfo, stock_purchase.card_number)
|
||||
return self.Session.get(MemberInfo, stock_purchase.card_number)
|
||||
|
||||
def configure_row_grid(self, g):
|
||||
super().configure_row_grid(g)
|
||||
|
@ -241,6 +265,9 @@ def defaults(config, **kwargs):
|
|||
MemberTypeView = kwargs.get('MemberTypeView', base['MemberTypeView'])
|
||||
MemberTypeView.defaults(config)
|
||||
|
||||
MemberContactPreferenceView = kwargs.get('MemberContactPreferenceView', base['MemberContactPreferenceView'])
|
||||
MemberContactPreferenceView.defaults(config)
|
||||
|
||||
MemberView = kwargs.get('MemberView', base['MemberView'])
|
||||
MemberView.defaults(config)
|
||||
|
||||
|
|
|
@ -248,7 +248,8 @@ class ProductView(CoreOfficeMasterView):
|
|||
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
key='{}.vendor_items'.format(route_prefix),
|
||||
self.request,
|
||||
key=f'{route_prefix}.vendor_items',
|
||||
data=[],
|
||||
columns=[
|
||||
'vendor_name',
|
||||
|
|
50
tailbone_corepos/views/corepos/receipts.py
Normal file
50
tailbone_corepos/views/corepos/receipts.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2024 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
CORE POS receipt views
|
||||
"""
|
||||
|
||||
from corepos.db.office_op.model import CustomReceiptLine
|
||||
|
||||
from .master import CoreOfficeMasterView
|
||||
|
||||
|
||||
class CustomReceiptLineView(CoreOfficeMasterView):
|
||||
"""
|
||||
Master view for custom receipt text
|
||||
"""
|
||||
model_class = CustomReceiptLine
|
||||
model_title = "CORE-POS Custom Receipt Line"
|
||||
route_prefix = 'corepos.custom_receipt_lines'
|
||||
url_prefix = '/core-pos/custom-receipt-lines'
|
||||
|
||||
|
||||
def defaults(config, **kwargs):
|
||||
base = globals()
|
||||
|
||||
CustomReceiptLineView = kwargs.get('CustomReceiptLineView', base['CustomReceiptLineView'])
|
||||
CustomReceiptLineView.defaults(config)
|
||||
|
||||
|
||||
def includeme(config):
|
||||
defaults(config)
|
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2023 Lance Edgar
|
||||
# Copyright © 2010-2024 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -68,6 +68,30 @@ class PersonViewSupplement(ViewSupplement):
|
|||
|
||||
return context
|
||||
|
||||
def get_context_for_member(self, member, context):
|
||||
|
||||
if member.corepos_card_number:
|
||||
app = self.get_rattail_app()
|
||||
corepos = app.get_corepos_handler()
|
||||
url = corepos.get_office_member_url(member.corepos_card_number)
|
||||
if url:
|
||||
context['external_links'].append({'label': "View in CORE Office",
|
||||
'url': url})
|
||||
|
||||
return context
|
||||
|
||||
def get_context_for_employee(self, employee, context):
|
||||
|
||||
if employee.corepos_number:
|
||||
app = self.get_rattail_app()
|
||||
corepos = app.get_corepos_handler()
|
||||
url = corepos.get_office_employee_url(employee.corepos_number)
|
||||
if url:
|
||||
context['external_links'].append({'label': "View in CORE Office",
|
||||
'url': url})
|
||||
|
||||
return context
|
||||
|
||||
def get_member_xref_buttons(self, person):
|
||||
buttons = OrderedDict()
|
||||
app = self.get_rattail_app()
|
||||
|
|
2
tasks.py
2
tasks.py
|
@ -52,6 +52,6 @@ def release(c):
|
|||
"""
|
||||
if os.path.exists('tailbone_corepos.egg-info'):
|
||||
shutil.rmtree('tailbone_corepos.egg-info')
|
||||
c.run('python setup.py sdist --formats=gztar')
|
||||
c.run('python -m build --sdist')
|
||||
filename = f'tailbone_corepos-{__version__}.tar.gz'
|
||||
c.run('twine upload dist/{}'.format(filename))
|
||||
|
|
Loading…
Reference in a new issue