Stored procedure helpers. Order repo and model. More SQLService updates.
* A generic stored procedure helper added, and support for calling them. * Order and OrderItem tables added, including helpers and calls to SP for creation and updates. * Minor updates to other repositories.
This commit is contained in:
parent
b77a7069ce
commit
0af38e286e
9 changed files with 730 additions and 138 deletions
|
|
@ -5,50 +5,38 @@
|
|||
|
||||
Jeeves raw data models
|
||||
"""
|
||||
# from sqlalchemy import Column, String
|
||||
from sqlalchemy.schema import MetaData, ForeignKey, Column
|
||||
|
||||
from sqlalchemy.schema import ForeignKey, Column
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.types import Integer, String
|
||||
from sqlalchemy.ext.automap import automap_base
|
||||
|
||||
from sqlalchemy.ext.hybrid import hybrid_property
|
||||
from sqlalchemy.sql.expression import and_
|
||||
from sqlalchemy.exc import OperationalError
|
||||
|
||||
from . import db
|
||||
|
||||
from pyjeeves import logging
|
||||
from .abc import RawBaseModel
|
||||
from .sp_classes import OrderHead, OrderRow, PlaceOrder
|
||||
|
||||
import re
|
||||
|
||||
logger = logging.getLogger("PyJeeves." + __name__)
|
||||
logger.info("Reading Jeeves DB structure")
|
||||
|
||||
meta = MetaData()
|
||||
try:
|
||||
meta.reflect(bind=db.raw_session.connection(),
|
||||
only=['ar', 'ars', 'xae', 'xare', 'fr', 'kus', 'x1k',
|
||||
'oh', 'lp', 'vg', 'xp', 'xm', 'prh', 'prl'])
|
||||
except OperationalError as e:
|
||||
logger.error("Failed to read Jeeves DB structure")
|
||||
raise e
|
||||
|
||||
Base = automap_base(cls=db.Model, name='Model', metadata=meta)
|
||||
|
||||
|
||||
class ProductClass(Base, RawBaseModel):
|
||||
class ProductClass(RawBaseModel):
|
||||
__tablename__ = 'xp'
|
||||
__column_map__ = {'ArtProdKlass': 'ProductClassNumber', 'ArtProdklBeskr': 'ProductClassName'}
|
||||
__to_dict_only__ = ('ArtProdKlass', 'ArtProdklBeskr')
|
||||
# print_filter = ('Articles', 'articles_collection')
|
||||
|
||||
|
||||
class ArticleClass(Base, RawBaseModel):
|
||||
class ArticleClass(RawBaseModel):
|
||||
__tablename__ = 'xm'
|
||||
__column_map__ = {'ArtKod': 'ArticleClassNumber', 'ArtTypBeskr': 'ArticleClassName'}
|
||||
__to_dict_only__ = ('ArtKod', 'ArtTypBeskr')
|
||||
# print_filter = ('Articles', 'articles_collection')
|
||||
|
||||
|
||||
class CommodityGroup(Base, RawBaseModel):
|
||||
class CommodityGroup(RawBaseModel):
|
||||
__tablename__ = 'vg'
|
||||
__column_map__ = {'VaruGruppKod': 'CommodityGroupNumber',
|
||||
'VaruGruppBeskr': 'CommodityGroupName'}
|
||||
|
|
@ -61,14 +49,14 @@ class CommodityGroup(Base, RawBaseModel):
|
|||
ArticleClass = relationship(ArticleClass)
|
||||
|
||||
|
||||
class ArticleAlternativeUnit(Base, RawBaseModel):
|
||||
class ArticleAlternativeUnit(RawBaseModel):
|
||||
__tablename__ = 'xae'
|
||||
__column_map__ = {'AltEnhetKod': 'UnitCode', 'AltEnhetBeskr': 'UnitName',
|
||||
'AltEnhetOmrFaktor': 'DefaultUnitConv'}
|
||||
__to_dict_only__ = ('AltEnhetBeskr', 'AltEnhetOmrFaktor')
|
||||
|
||||
|
||||
class ArticleUnit(Base, RawBaseModel):
|
||||
class ArticleUnit(RawBaseModel):
|
||||
__tablename__ = 'xare'
|
||||
__column_map__ = {'ArtNr': 'ArticleNumber',
|
||||
'AltEnhetKod': 'UnitCode', 'AltEnhetOmrFaktor': 'UnitConv',
|
||||
|
|
@ -82,7 +70,7 @@ class ArticleUnit(Base, RawBaseModel):
|
|||
ArticleAlternativeUnit = relationship(ArticleAlternativeUnit)
|
||||
|
||||
|
||||
class ArticleBalance(Base, RawBaseModel):
|
||||
class ArticleBalance(RawBaseModel):
|
||||
__tablename__ = 'ars'
|
||||
__column_map__ = {'LagSaldo': 'Balance',
|
||||
'LagResAnt': 'ReservedBalance',
|
||||
|
|
@ -100,7 +88,7 @@ class ArticleBalance(Base, RawBaseModel):
|
|||
ArtNr = Column(Integer, ForeignKey('ar.ArtNr'), primary_key=True)
|
||||
|
||||
|
||||
class Article(Base, RawBaseModel):
|
||||
class Article(RawBaseModel):
|
||||
__tablename__ = 'ar'
|
||||
|
||||
__column_map__ = {'ArtNr': 'ArticleNumber',
|
||||
|
|
@ -178,7 +166,7 @@ class Article(Base, RawBaseModel):
|
|||
)
|
||||
|
||||
|
||||
class Company(Base, RawBaseModel):
|
||||
class Company(RawBaseModel):
|
||||
__tablename__ = 'fr'
|
||||
__column_map__ = {'FtgNr': 'CompanyNumber', 'FtgNamn': 'CompanyName'}
|
||||
__to_dict_only__ = ('FtgNr', 'FtgNamn', 'Customer')
|
||||
|
|
@ -188,13 +176,17 @@ class Company(Base, RawBaseModel):
|
|||
Customer = relationship('Customer', uselist=False, back_populates='Company', lazy='joined')
|
||||
|
||||
|
||||
class CustomerCategory(Base, RawBaseModel):
|
||||
class DelivLoc(RawBaseModel):
|
||||
__tablename__ = 'lp'
|
||||
|
||||
|
||||
class CustomerCategory(RawBaseModel):
|
||||
__tablename__ = 'x1k'
|
||||
|
||||
KundKategoriKod = Column(Integer, primary_key=True)
|
||||
|
||||
|
||||
class Customer(Base, RawBaseModel):
|
||||
class Customer(RawBaseModel):
|
||||
__tablename__ = 'kus'
|
||||
__column_map__ = {'FtgNr': 'CompanyNumber', 'kundkategorikod': 'CustomerCategoryCode',
|
||||
'PrisListaKundSpec': 'PriceListPrimary', 'PrisLista': 'PriceListSecondary'}
|
||||
|
|
@ -218,10 +210,10 @@ class Customer(Base, RawBaseModel):
|
|||
|
||||
@hybrid_property
|
||||
def CustomerCategory(self):
|
||||
return self.KundKategori.KundKatBeskr
|
||||
return self.KundKategori.KundKatBeskr if self.KundKategori else ""
|
||||
|
||||
|
||||
class PriceList(Base, RawBaseModel):
|
||||
class PriceList(RawBaseModel):
|
||||
__tablename__ = 'prh'
|
||||
__column_map__ = {'PrisListaBeskr': 'Description', 'PrisLista': 'PriceListNumber',
|
||||
'MarkUpBelopp': 'PriceFactor'}
|
||||
|
|
@ -234,7 +226,7 @@ class PriceList(Base, RawBaseModel):
|
|||
PriceListItems = relationship('PriceListItem', back_populates="PriceList", lazy='joined')
|
||||
|
||||
|
||||
class PriceListItem(Base, RawBaseModel):
|
||||
class PriceListItem(RawBaseModel):
|
||||
__tablename__ = 'prl'
|
||||
__column_map__ = {'ArtNr': 'ArticleNumber', 'vb_pris': 'UnitPrice',
|
||||
'MarkUpBelopp': 'UnitPriceFactor', 'NollFaktor': 'NullPriceAllowed'}
|
||||
|
|
@ -272,8 +264,123 @@ class PriceListItem(Base, RawBaseModel):
|
|||
self.Article.get_unit_conv())
|
||||
|
||||
|
||||
Base.prepare()
|
||||
class Order(RawBaseModel):
|
||||
__tablename__ = 'oh'
|
||||
__column_map__ = {'OrderNr': 'OrderNumber', 'FtgNr': 'CompanyNumber',
|
||||
'OrdDatum': 'OrderDate', 'OrdStat': 'OrderStatusCode',
|
||||
'OrdLevAdr1': 'AddrName', 'OrdLevAdr2': 'AddrCO',
|
||||
'OrdLevAdr3': 'AddrStreet', 'OrdLevAdrLandsKod': 'AddrCountry',
|
||||
'KundBestNr': 'CustomerContact', 'KundRef2': 'CustomerReference',
|
||||
'GodsMarke1': 'ShippingInfo', 'GodsMarke2': 'InternalInfo',
|
||||
'TA_MailNotified': 'ShippingEmail', 'TA_PhonNotifiedNo': 'ShippingPhone',
|
||||
'TA_SMSNotifiedNo': 'ShippingSMS', 'LevSattKod': 'ShippingTypeCode'}
|
||||
__to_dict_only__ = ('OrderNr', 'FtgNr', 'OrdDatum', 'OrdStat', 'CompanyName', 'LevSattKod',
|
||||
'OrdLevAdr1', 'OrdLevAdr2', 'OrdLevAdr3',
|
||||
'OrdLevAdrLandsKod', 'KundBestNr', 'KundRef2', 'GodsMarke1',
|
||||
'GodsMarke2', 'OrderItems', 'AddrPostalCode', 'AddrCity',
|
||||
'TA_MailNotified', 'TA_PhonNotifiedNo', 'TA_SMSNotifiedNo')
|
||||
|
||||
# Base companies for cusomters and suppliers
|
||||
Order = Base.classes.oh # Orders by customers
|
||||
DelivLoc = Base.classes.lp # Connections between a delivery company and customer company
|
||||
__dict_args__ = {
|
||||
'adapters': {
|
||||
**{
|
||||
'OrdDatum': lambda ord_date, *_: ord_date.strftime("%Y-%m-%d"),
|
||||
},
|
||||
**RawBaseModel.__dict_args__['adapters']
|
||||
}
|
||||
}
|
||||
|
||||
OrderNr = Column(Integer, primary_key=True)
|
||||
FtgNr = Column(String, ForeignKey('fr.FtgNr'))
|
||||
|
||||
Company = relationship('Company', uselist=False)
|
||||
OrderItems = relationship('OrderItem', uselist=True, back_populates="Order", lazy='joined')
|
||||
|
||||
@hybrid_property
|
||||
def CompanyName(self):
|
||||
return self.Company.FtgNamn if self.Company else ""
|
||||
|
||||
@CompanyName.setter
|
||||
def CompanyName(self, value):
|
||||
return
|
||||
|
||||
@hybrid_property
|
||||
def AddrPostalCode(self):
|
||||
if not self.OrdLevAdr4:
|
||||
return
|
||||
s = re.split('(?!\d)\s(?!\d)', self.OrdLevAdr4)
|
||||
return s[0] if len(s) > 1 else ''
|
||||
|
||||
@AddrPostalCode.setter
|
||||
def AddrPostalCode(self, value):
|
||||
self.OrdLevAdr4 = value + (self.OrdLevAdr4 if self.OrdLevAdr4 else '')
|
||||
|
||||
@hybrid_property
|
||||
def AddrCity(self):
|
||||
if not self.OrdLevAdr4:
|
||||
return
|
||||
s = re.split('(?!\d)\s(?!\d)', self.OrdLevAdr4, maxsplit=1)
|
||||
return s[1] if len(s) > 1 else ''
|
||||
|
||||
@AddrCity.setter
|
||||
def AddrCity(self, value):
|
||||
self.OrdLevAdr4 = (self.OrdLevAdr4 if self.OrdLevAdr4 else '') + ' ' + value
|
||||
|
||||
def create(self, webusername=None):
|
||||
# TODO: Extend with additional functionlity if desired.
|
||||
self['OrderNr'], invoicing_possible = OrderHead(self['FtgNr'], webusername).callproc()
|
||||
return self, invoicing_possible
|
||||
|
||||
def save(self, invoiced=False):
|
||||
payment_method = 'invoice'
|
||||
if not invoiced:
|
||||
payment_method = 'card'
|
||||
PlaceOrder(
|
||||
self['FtgNr'], self['OrderNr'], payment_method, data=self.to_dict()).callproc()
|
||||
|
||||
return self
|
||||
|
||||
|
||||
class OrderItem(RawBaseModel):
|
||||
__tablename__ = 'orp'
|
||||
__column_map__ = {'OrdRadNr': 'OrderRowNumber', 'vb_pris': 'UnitPrice',
|
||||
'ArtNr': 'ArticleNumber', 'OrdAntal': 'UnitAmount',
|
||||
'OrdAntalAltEnh': 'AltUnitAmount', 'AltEnhetKod': 'AltUnit'}
|
||||
__to_dict_only__ = ('OrdRadNr', 'vb_pris', 'ArtNr', 'ArticleName', 'OrdAntal',
|
||||
'OrdAntalAltEnh', 'AltEnhetKod')
|
||||
|
||||
# Do not serialize order relationship
|
||||
__dict_args__ = {
|
||||
'adapters': {
|
||||
**{
|
||||
Order: None,
|
||||
},
|
||||
**RawBaseModel.__dict_args__['adapters']
|
||||
}
|
||||
}
|
||||
|
||||
OrderNr = Column(Integer, ForeignKey('oh.OrderNr'), primary_key=True)
|
||||
OrdRadNr = Column(Integer, primary_key=True)
|
||||
OrdRadNrStrPos = Column(Integer, primary_key=True)
|
||||
OrdRestNr = Column(Integer, primary_key=True)
|
||||
|
||||
ArtNr = Column(Integer, ForeignKey('ar.ArtNr'))
|
||||
|
||||
Order = relationship('Order', uselist=False)
|
||||
Article = relationship(Article)
|
||||
|
||||
@hybrid_property
|
||||
def ArticleName(self):
|
||||
return self.Article.ArtBeskr if self.Article else ""
|
||||
|
||||
@ArticleName.setter
|
||||
def ArticleName(self, value):
|
||||
return
|
||||
|
||||
def save(self):
|
||||
# TODO: Additional information may be returned if desired.
|
||||
row_no = OrderRow(
|
||||
company_no=self['FtgNr'], order_no=self['OrderNr'], item_no=self['ArtNr'],
|
||||
qty=self['OrdAntal'], qty_alt_unit=self['OrdAntalAltEnh'],
|
||||
alt_unit=self['AltEnhetKod'], pers_sign='marlin').callproc()
|
||||
self['OrdRadNr'] = row_no
|
||||
return self
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue