sideshow.batch.neworder

New Order Batch Handler

class sideshow.batch.neworder.NewOrderBatchHandler(config)[source]

The batch handler for new order batches.

This is responsible for business logic around the creation of new orders. A NewOrderBatch tracks all user input until they “submit” (execute) at which point an Order is created.

add_item(batch, product_info, order_qty, order_uom, user=None)[source]

Add a new item/row to the batch, for given product and quantity.

See also update_item().

Parameters:
  • batchNewOrderBatch to update.

  • product_info – Product ID string, or dict of PendingProduct data.

  • order_qtyorder_qty value for the new row.

  • order_uomorder_uom value for the new row.

  • userUser who is performing the action. This is used to set created_by on the pending product, if applicable. If not specified, the batch creator is assumed.

Returns:

NewOrderBatchRow instance.

allow_unknown_products()[source]

Returns boolean indicating whether pending products are allowed when creating an order.

This is true by default, so user can enter new/unknown product when creating an order. This can be disabled, to force user to choose existing local/external product.

autocomplete_customers_external(session, term, user=None)[source]

Return autocomplete search results for external customer records.

There is no default logic here; subclass must implement.

Parameters:
  • session – Current app db session.

  • term – Search term string from user input.

  • userUser who is doing the search, if known.

Returns:

List of search results; each should be a dict with value and label keys.

autocomplete_customers_local(session, term, user=None)[source]

Return autocomplete search results for LocalCustomer records.

Parameters:
  • session – Current app db session.

  • term – Search term string from user input.

  • userUser who is doing the search, if known.

Returns:

List of search results; each should be a dict with value and label keys.

autocomplete_products_external(session, term, user=None)[source]

Return autocomplete search results for external product records.

There is no default logic here; subclass must implement.

Parameters:
  • session – Current app db session.

  • term – Search term string from user input.

  • userUser who is doing the search, if known.

Returns:

List of search results; each should be a dict with value and label keys.

autocomplete_products_local(session, term, user=None)[source]

Return autocomplete search results for LocalProduct records.

Parameters:
  • session – Current app db session.

  • term – Search term string from user input.

  • userUser who is doing the search, if known.

Returns:

List of search results; each should be a dict with value and label keys.

do_delete(batch, user, **kwargs)[source]

Delete a batch completely.

If the batch has pending customer or pending product records, they are also deleted - unless still referenced by some order(s).

execute(batch, user=None, progress=None, **kwargs)[source]

Execute the batch; this should make a proper order.

By default, this will call:

And will return the new Order instance.

Note that callers should use do_execute() instead, which calls this method automatically.

get_effective_rows(batch)[source]

Only rows with STATUS_OK are “effective” - i.e. rows with other status codes will not be created as proper order items.

get_product_info_external(session, product_id, user=None)[source]

Returns basic info for an external product as pertains to ordering.

When user has located a product via search, and must then choose order quantity and UOM based on case size, pricing etc., this method is called to retrieve the product info.

There is no default logic here; subclass must implement.

Parameters:
  • session – Current app db session.

  • product_id – Product ID string for which to retrieve info.

  • userUser who is performing the action, if known.

Returns:

Dict of product info. Should raise error instead of returning None if product not found.

This method should only be called after a product has been identified via autocomplete/search lookup; therefore the product_id should be valid, and the caller can expect this method to always return a dict. If for some reason the product cannot be found here, an error should be raised.

The dict should contain as much product info as is available and needed; if some are missing it should not cause too much trouble in the app. Here is a basic example:

def get_product_info_external(self, session, product_id, user=None):
    ext_model = get_external_model()
    ext_session = make_external_session()

    ext_product = ext_session.get(ext_model.Product, product_id)
    if not ext_product:
        ext_session.close()
        raise ValueError(f"external product not found: {product_id}")

    info = {
        'product_id': product_id,
        'scancode': product.scancode,
        'brand_name': product.brand_name,
        'description': product.description,
        'size': product.size,
        'weighed': product.sold_by_weight,
        'special_order': False,
        'department_id': str(product.department_number),
        'department_name': product.department_name,
        'case_size': product.case_size,
        'unit_price_reg': product.unit_price_reg,
        'vendor_name': product.vendor_name,
        'vendor_item_code': product.vendor_item_code,
    }

    ext_session.close()
    return info
get_product_info_local(session, uuid, user=None)[source]

Returns basic info for a LocalProduct as pertains to ordering.

When user has located a product via search, and must then choose order quantity and UOM based on case size, pricing etc., this method is called to retrieve the product info.

See get_product_info_external() for more explanation.

make_local_customer(batch)[source]

If applicable, this converts the batch pending customer into a local customer.

This is called automatically from execute().

This logic will happen only if use_local_customers() returns true, and the batch has pending instead of local customer (so far).

It will create a new LocalCustomer record and populate it from the batch pending_customer. The latter is then deleted.

make_local_products(batch, rows)[source]

If applicable, this converts all pending products into local products.

This is called automatically from execute().

This logic will happen only if use_local_products() returns true, and the batch has pending instead of local items (so far).

For each affected row, it will create a new LocalProduct record and populate it from the row pending_product. The latter is then deleted.

make_new_order(batch, rows, user=None, progress=None, **kwargs)[source]

Create a new order from the batch data.

This is called automatically from execute().

Parameters:
  • batchNewOrderBatch instance.

  • rows – List of effective rows for the batch, i.e. which rows should be converted to order items.

Returns:

Order instance.

model_class

alias of NewOrderBatch

refresh_batch_from_external_customer(batch)[source]

Update customer-related attributes on the batch, from its external customer record.

This is called automatically from set_customer().

There is no default logic here; subclass must implement.

refresh_batch_from_local_customer(batch)[source]

Update customer-related attributes on the batch, from its local_customer record.

This is called automatically from set_customer().

refresh_batch_from_pending_customer(batch)[source]

Update customer-related attributes on the batch, from its pending_customer record.

This is called automatically from set_customer().

refresh_row(row)[source]

Refresh data for the row. This is called when adding a new row to the batch, or anytime the row is updated (e.g. when changing order quantity).

This calls one of the following to update product-related attributes:

It then re-calculates the row’s total_price and updates the batch accordingly.

It also sets the row status_code.

refresh_row_from_external_product(row)[source]

Update product-related attributes on the row, from its external product record indicated by product_id.

This is called automatically from refresh_row().

There is no default logic here; subclass must implement as needed.

refresh_row_from_local_product(row)[source]

Update product-related attributes on the row, from its local_product record.

This is called automatically from refresh_row().

refresh_row_from_pending_product(row)[source]

Update product-related attributes on the row, from its pending_product record.

This is called automatically from refresh_row().

remove_row(row)[source]

Remove a row from its batch.

This also will update the batch total_price accordingly.

set_customer(batch, customer_info, user=None)[source]

Set/update customer info for the batch.

This will first set one of the following:

Note that a new PendingCustomer record is created if necessary.

And then it will update customer-related attributes via one of:

Note that customer_info may be None, which will cause customer attributes to be set to None also.

Parameters:
  • batchNewOrderBatch to update.

  • customer_info – Customer ID string, or dict of PendingCustomer data, or None to clear the customer info.

  • userUser who is performing the action. This is used to set created_by on the pending customer, if applicable. If not specified, the batch creator is assumed.

update_item(row, product_info, order_qty, order_uom, user=None)[source]

Update an item/row, per given product and quantity.

See also add_item().

Parameters:
  • rowNewOrderBatchRow to update.

  • product_info – Product ID string, or dict of PendingProduct data.

  • order_qty – New order_qty value for the row.

  • order_uom – New order_uom value for the row.

  • userUser who is performing the action. This is used to set created_by on the pending product, if applicable. If not specified, the batch creator is assumed.

use_local_customers()[source]

Returns boolean indicating whether local customer accounts should be used. This is true by default, but may be false for external customer lookups.

use_local_products()[source]

Returns boolean indicating whether local product records should be used. This is true by default, but may be false for external product lookups.

why_not_execute(batch, **kwargs)[source]

By default this checks to ensure the batch has a customer with phone number, and at least one item.