From 6339e9d1ce36804c0be9fb3c3936f73f4349113a Mon Sep 17 00:00:00 2001 From: Marcus Lindvall Date: Mon, 23 Sep 2019 14:12:34 +0200 Subject: [PATCH] Fixes to pricing and customer models. Add req deliv to order. And more.. * Fix NullPriceAllowed and logic in price calculation * Fix CustomerCategory join in Customer model * Add RequestedDeliveryDate to order creation * Start using Jeeves Signatures on order creation --- pyjeeves/models/raw.py | 35 ++++++++++++++++++++++---------- pyjeeves/models/sp_classes.py | 12 +++++++---- pyjeeves/repositories/company.py | 23 +++++++++++++++++---- pyjeeves/repositories/order.py | 17 +++++++++++----- 4 files changed, 63 insertions(+), 24 deletions(-) diff --git a/pyjeeves/models/raw.py b/pyjeeves/models/raw.py index 7a8ca3c..3e5af38 100644 --- a/pyjeeves/models/raw.py +++ b/pyjeeves/models/raw.py @@ -301,7 +301,6 @@ class Customer(RawBaseModel): 'GodsMarke2', 'LevSattKod', 'Language', 'ValKod') FtgNr = Column(String, ForeignKey('fr.FtgNr'), primary_key=True) - KundKategoriKod = Column(Integer, ForeignKey('x1k.KundKategoriKod')) SprakKod = Column(Integer, ForeignKey('xw.SprakKod')) PrisLista = Column(Integer, ForeignKey('prh.PrisLista')) PrisListaKundSpec = Column(Integer, ForeignKey('prh.PrisLista')) @@ -314,7 +313,9 @@ class Customer(RawBaseModel): foreign_keys='PriceList.PrisLista', primaryjoin="Customer.PrisLista==PriceList.PrisLista") - KundKategori = relationship("CustomerCategory") + KundKategori = relationship( + "CustomerCategory", uselist=False, foreign_keys='CustomerCategory.KundKategoriKod', + primaryjoin="Customer.kundkategorikod==CustomerCategory.KundKategoriKod") LanguageCodes = relationship("LanguageCodes") WebUsers = relationship( @@ -346,8 +347,8 @@ class PriceList(RawBaseModel): class PriceListItem(RawBaseModel): __tablename__ = 'prl' __column_map__ = {'ArtNr': 'ArticleNumber', 'vb_pris': 'UnitPrice', - 'MarkUpBelopp': 'UnitPriceFactor', 'NollFaktor': 'NullPriceAllowed'} - __to_dict_only__ = ('ArtNr', 'vb_pris', 'MarkUpBelopp', 'NollFaktor', 'Price') + 'MarkUpBelopp': 'UnitPriceFactor', 'KodNollPris': 'NullPriceAllowed'} + __to_dict_only__ = ('ArtNr', 'vb_pris', 'MarkUpBelopp', 'KodNollPris', 'Price') __to_dict_filter__ = ['PriceList'] # Do not serialize price list relationship @@ -370,8 +371,12 @@ class PriceListItem(RawBaseModel): @hybrid_property def Price(self): if not self.vb_pris and not self.MarkUpBelopp: + if self.KodNollPris == "1": + return 0 + + MarkUpBelop = self.PriceList.MarkUpBelopp if self.PriceList.MarkUpBelopp else 0 return ( - (self.Article.ArtListPris + self.PriceList.MarkUpBelopp) * + (self.Article.ArtListPris + MarkUpBelop) * self.Article.get_unit_conv()) if self.vb_pris: return self.vb_pris * self.Article.get_unit_conv() @@ -390,9 +395,10 @@ class Order(RawBaseModel): 'KundBestNr': 'CustomerContact', 'KundRef2': 'CustomerReference', 'GodsMarke1': 'ShippingInfo', 'GodsMarke2': 'InternalInfo', 'TA_MailNotified': 'ShippingEmail', 'TA_PhonNotifiedNo': 'ShippingPhone', - 'TA_SMSNotifiedNo': 'ShippingSMS', 'LevSattKod': 'ShippingTypeCode'} + 'TA_SMSNotifiedNo': 'ShippingSMS', 'LevSattKod': 'ShippingTypeCode', + 'OrdBerLevDat': 'RequestedDeliveryDate'} __to_dict_only__ = ('OrderNr', 'FtgNr', 'OrdDatum', 'OrdStat', 'CompanyName', 'LevSattKod', - 'OrdLevAdr1', 'OrdLevAdr2', 'OrdLevAdr3', + 'OrdLevAdr1', 'OrdLevAdr2', 'OrdLevAdr3', 'OrdBerLevDat', 'OrdLevAdrLandsKod', 'KundBestNr', 'KundRef2', 'GodsMarke1', 'GodsMarke2', 'OrderItems', 'AddrPostalCode', 'AddrCity', 'TA_MailNotified', 'TA_PhonNotifiedNo', 'TA_SMSNotifiedNo') @@ -401,6 +407,7 @@ class Order(RawBaseModel): 'adapters': { **{ 'OrdDatum': lambda ord_date, *_: ord_date.strftime("%Y-%m-%d"), + 'OrdBerLevDat': lambda ord_date, *_: ord_date.strftime("%Y-%m-%d"), }, **RawBaseModel.__dict_args__['adapters'] } @@ -444,7 +451,8 @@ class Order(RawBaseModel): def create(self, webusername=None): # TODO: Extend with additional functionlity if desired. - self['OrderNr'], invoicing_possible = OrderHead(self['FtgNr'], webusername).callproc() + self['OrderNr'], invoicing_possible = OrderHead( + self['FtgNr'], webusername, pers_sign=self['PersSign']).callproc() return self, invoicing_possible def save(self, invoiced=False, webusername=None): @@ -462,15 +470,19 @@ class OrderItem(RawBaseModel): __tablename__ = 'orp' __column_map__ = {'OrdRadNr': 'OrderRowNumber', 'vb_pris': 'UnitPrice', 'ArtNr': 'ArticleNumber', 'OrdAntal': 'UnitAmount', - 'OrdAntalAltEnh': 'AltUnitAmount', 'AltEnhetKod': 'AltUnit'} + 'OrdAntalAltEnh': 'AltUnitAmount', 'AltEnhetKod': 'AltUnit', + 'OrdBegLevDat': 'RequestedDeliveryDate'} __to_dict_only__ = ('OrdRadNr', 'vb_pris', 'ArtNr', 'ArticleName', 'OrdAntal', - 'OrdAntalAltEnh', 'AltEnhetKod') + 'OrdAntalAltEnh', 'AltEnhetKod', 'OrdBegLevDat') # Do not serialize order relationship __dict_args__ = { 'adapters': { **{ Order: None, + 'OrdBegLevDat': lambda req_date, *_: ( + req_date.strftime("%Y-%m-%d") + if not isinstance(req_date, str) else req_date), }, **RawBaseModel.__dict_args__['adapters'] } @@ -499,6 +511,7 @@ class OrderItem(RawBaseModel): 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() + alt_unit=self['AltEnhetKod'], requested_date=self['OrdBegLevDat'], + pers_sign=self['PersSign']).callproc() self['OrdRadNr'] = row_no return self diff --git a/pyjeeves/models/sp_classes.py b/pyjeeves/models/sp_classes.py index 42ac6bb..886536d 100644 --- a/pyjeeves/models/sp_classes.py +++ b/pyjeeves/models/sp_classes.py @@ -3,6 +3,7 @@ import pymssql from collections import OrderedDict from pyjeeves.models import db from pyjeeves import logging +from datetime import date # from datetime import datetime # from decimal import Decimal @@ -102,14 +103,14 @@ class OrderHead(StoredProcedure): webapp031 and WEBAPP003 determines default order status""" # TODO: Extend with additional functionlity if desired. - def __init__(self, company_no, web_user_name): + def __init__(self, company_no, web_user_name, pers_sign='biz'): super(OrderHead, self).__init__('Jeeves_Esales_CreateOrder') self['c_CompanyNo'] = company_no # Some defaults: self['c_ForetagKod'] = 1 # Hardcoded to LK - self['c_PersSign'] = 'marlin' # From API profile, or default + self['c_PersSign'] = str(pers_sign) # From API profile, or default # self['c_OrderType'] = None # Default set by WEBAPP008 # self['c_TemplateRowID'] = None # No template used # self['c_Saljare'] = None # 600 # From API profile, or default @@ -140,7 +141,8 @@ class OrderRow(StoredProcedure): AltEnhetKod logic needs to have been added to the procedure""" def __init__(self, company_no, order_no, item_no, - qty=None, qty_alt_unit=None, alt_unit=None, pers_sign='biz'): + qty=None, qty_alt_unit=None, alt_unit=None, + requested_date=None, pers_sign='biz'): super(OrderRow, self).__init__('Jeeves_Esales_AddOrderRow') self['c_CompanyNo'] = str(company_no) @@ -152,7 +154,9 @@ class OrderRow(StoredProcedure): self['c_PersSign'] = str(pers_sign) # Used to set date for delivery (c_OrdBegLevDat) and (c_OrdBerLevDat) - self['c_RequestedDate'] = None + self['c_RequestedDate'] = ( + requested_date.strftime('%Y%m%d') + if isinstance(requested_date, date) else requested_date) # Some defaults: self['c_ForetagKod'] = 1 # Hardcoded to LK diff --git a/pyjeeves/repositories/company.py b/pyjeeves/repositories/company.py index c8d3bd7..6a8191e 100644 --- a/pyjeeves/repositories/company.py +++ b/pyjeeves/repositories/company.py @@ -3,6 +3,7 @@ from pyjeeves.models.raw import Company as CompanyModel, Customer as CustomerModel from pyjeeves.models import db from sqlalchemy.sql.expression import and_ +from sqlalchemy.orm.strategy_options import Load from pyjeeves import logging logger = logging.getLogger("PyJeeves." + __name__) @@ -25,10 +26,24 @@ class Company(): return [c.CompanyModel for c in cust] @staticmethod - def get_list(ftg_nr=[]): - return db.raw.query(CompanyModel).filter( - CompanyModel.FtgNr.in_(ftg_nr) - ).all() + def get_customer_numbers(category_list=[10], class_list=[], filter_inactive=True): + category_in = CustomerModel.kundkategorikod.in_(category_list) if category_list else and_() + class_in = CustomerModel.kundklass.in_(class_list) if class_list else and_() + inactive = and_(CustomerModel.Makulerad == 0) if filter_inactive else and_() + cust = db.raw.query(CustomerModel).options( + Load(CustomerModel).noload('*')).filter( + and_(category_in, class_in, inactive)).all() + return [c.FtgNr for c in cust] + + @staticmethod + def get_list(ftg_nr=[], filter_=and_(CustomerModel.Makulerad == 0), offset=0, limit=100): + ftg_filter = and_() + if ftg_nr: + ftg_filter = CompanyModel.FtgNr.in_(ftg_nr) + + return db.raw.query(CompanyModel).join(CustomerModel).filter( + and_(ftg_filter, filter_)).order_by( + CompanyModel.FtgNr.desc()).offset(offset).limit(limit).all() if __name__ == '__main__': diff --git a/pyjeeves/repositories/order.py b/pyjeeves/repositories/order.py index 3ac0464..f86ee6a 100644 --- a/pyjeeves/repositories/order.py +++ b/pyjeeves/repositories/order.py @@ -44,8 +44,9 @@ class Order(): ).all() @staticmethod - def create(customer_no, head={}, items=[], web_user_name=None): + def create(customer_no, head={}, items=[], web_user_name=None, pers_sign='biz'): head['CompanyNumber'] = str(customer_no) + head['PersSign'] = str(pers_sign) # Create order from head dict to get an order number order, invoice_possible = OrderModel(head).create(web_user_name) @@ -53,7 +54,7 @@ class Order(): raise # Go through order items, if any, and save them to DB. - order['OrderItems'] = Order.create_rows(order['FtgNr'], order['OrderNr'], items) + order['OrderItems'] = Order.create_rows(order, items) # Save the information in the order object # Boolean argument deceides if order has contact person, and should be set 'registered' @@ -62,14 +63,20 @@ class Order(): return order @staticmethod - def create_rows(company_no, order_no, items=[]): + def create_rows(order, items=[], pers_sign='biz'): rv = [] for item in items: if not isinstance(item, OrderItemModel): item = OrderItemModel(item) - item['OrderNr'] = order_no - item['FtgNr'] = company_no + + # Set RequestedDeliveryDate from order head if not specified for items. + if order['OrdBerLevDat'] and not item['OrdBegLevDat']: + item['OrdBegLevDat'] = order['OrdBerLevDat'] + + item['OrderNr'] = order['OrderNr'] + item['FtgNr'] = order['FtgNr'] + item['PersSign'] = pers_sign rv.append(item.save()) return rv