Add custom vendor catalog batch handler for CORE
capable of directly updating `vendorItems` etc. via CORE API
This commit is contained in:
parent
1be258246c
commit
d0bb4b105d
0
rattail_corepos/batch/__init__.py
Normal file
0
rattail_corepos/batch/__init__.py
Normal file
149
rattail_corepos/batch/vendorcatalog.py
Normal file
149
rattail_corepos/batch/vendorcatalog.py
Normal file
|
@ -0,0 +1,149 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2021 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/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Handler for Vendor Catalog batches
|
||||
"""
|
||||
|
||||
import decimal
|
||||
|
||||
from rattail.batch import vendorcatalog as base
|
||||
from rattail_corepos.corepos.api import make_corepos_api
|
||||
|
||||
|
||||
class VendorCatalogHandler(base.VendorCatalogHandler):
|
||||
"""
|
||||
Handler for vendor catalog batches.
|
||||
"""
|
||||
# default logic tries to update versions after execution, but since we just
|
||||
# update CORE-POS via API there's no need
|
||||
version_catchup_execute = None
|
||||
|
||||
def add_row(self, batch, row):
|
||||
|
||||
# CORE unit costs seem to be rounded to 3 decimal places
|
||||
if row.unit_cost:
|
||||
row.unit_cost = row.unit_cost.quantize(decimal.Decimal('0.123'))
|
||||
|
||||
# CORE bases its cost off the unit instead of case. so here we make
|
||||
# sure the case cost is cleanly derived from unit cost.
|
||||
if row.case_cost and row.unit_cost and row.case_size:
|
||||
row.case_cost = row.unit_cost * row.case_size
|
||||
|
||||
# okay now continue as normal
|
||||
super(VendorCatalogHandler, self).add_row(batch, row)
|
||||
|
||||
def describe_execution(self, batch, **kwargs):
|
||||
return ("The `vendorItems` table in CORE-POS will be updated directly "
|
||||
"via API, for all rows indicating a change etc. You may also "
|
||||
"update `products.cost` if desired.")
|
||||
|
||||
def execute(self, batch, progress=None, **kwargs):
|
||||
"""
|
||||
Update CORE-POS etc.
|
||||
"""
|
||||
rows = [row for row in batch.active_rows()
|
||||
if row.status_code in (row.STATUS_NEW_COST,
|
||||
row.STATUS_UPDATE_COST,
|
||||
row.STATUS_CHANGE_VENDOR_ITEM_CODE,
|
||||
row.STATUS_CHANGE_CASE_SIZE,
|
||||
row.STATUS_CHANGE_COST)]
|
||||
|
||||
if rows:
|
||||
vendor_id = batch.vendor.corepos_id
|
||||
if not vendor_id:
|
||||
raise ValueError("Batch vendor does not have valid CORE-POS ID")
|
||||
|
||||
self.api = make_corepos_api(self.config)
|
||||
self.update_corepos(batch, rows, vendor_id, progress=progress,
|
||||
# update_product_costs=kwargs.get('update_product_costs', False),
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
def update_corepos(self, batch, rows, vendor_id, progress=None,
|
||||
# TODO: this kwarg seems perhaps useful, but for now we
|
||||
# are auto-detecting when such an update is needed
|
||||
#update_product_costs=False,
|
||||
):
|
||||
"""
|
||||
Update the `vendorItems` table in CORE-POS (and maybe `products` too).
|
||||
"""
|
||||
def update(row, i):
|
||||
# we may need this value in a couple places
|
||||
unit_cost = float(row.unit_cost)
|
||||
|
||||
# we will want to set default vendor for the product, if it does
|
||||
# not yet have one
|
||||
first_vendor = False
|
||||
if not row.product.costs:
|
||||
first_vendor = True
|
||||
# core_product = self.api.get_product(row.item_id)
|
||||
# if not core_product['default_vendor_id']:
|
||||
# first_vendor = True
|
||||
|
||||
# figure out if we are "updating the same, primary" cost record,
|
||||
# b/c if so we will want to update product accordingly also. this
|
||||
# is always the case when this is the first vendor for product.
|
||||
updating_primary = first_vendor
|
||||
if not updating_primary:
|
||||
cost = row.product.cost
|
||||
if cost and cost is row.cost:
|
||||
updating_primary = True
|
||||
# core_items = self.api.get_vendor_items(upc=row.item_id)
|
||||
# if core_items:
|
||||
# core_item = core_items[0]
|
||||
# if core_item['sku'] == row.vendor_code:
|
||||
# updating_primary = True
|
||||
|
||||
# create or update the `vendorItems` record in CORE
|
||||
self.api.set_vendor_item(sku=row.vendor_code,
|
||||
vendorID=vendor_id,
|
||||
upc=row.item_id,
|
||||
brand=row.brand_name,
|
||||
description=row.description,
|
||||
size=row.size,
|
||||
units=row.case_size,
|
||||
cost=unit_cost,
|
||||
# TODO: we (may) have vendor SRP, but pretty
|
||||
# sure CORE has different plans for its `srp`
|
||||
#srp=row.suggested_retail,
|
||||
)
|
||||
|
||||
# TODO: CORE does not have the concept of a true "default"
|
||||
# `vendorItems` record, but rather uses the `modified` timestamp
|
||||
# for pseudo-default. this means any given product may wind up
|
||||
# with a new/different pseudo-default when the above operation
|
||||
# completes. in which case, perhaps we should *always* update
|
||||
# `products.cost` accordingly (below)..? er, still only if the
|
||||
# product's `default_vendor_id` matches at least, i guess... for
|
||||
# now we are only doing so if it "obviously" needs it.
|
||||
|
||||
# maybe also update `products` record in CORE
|
||||
if updating_primary:
|
||||
kwargs = {'cost': unit_cost}
|
||||
if first_vendor:
|
||||
kwargs['default_vendor_id'] = vendor_id
|
||||
self.api.set_product(upc=row.item_id, **kwargs)
|
||||
|
||||
self.progress_loop(update, rows, progress,
|
||||
message="Updating CORE-POS via API")
|
Loading…
Reference in a new issue