Example #1
0
def test_recreate_batch():
    state = InventoryStateMachine()
    v1 = state.new_anonymous_batch(batch=Batch(associated_codes=[],
                                               id='BAT000001',
                                               owned_codes=[],
                                               props=None,
                                               sku_id=None))
    state.delete_unused_batch(batch_id=v1)
    state.new_anonymous_batch(batch=Batch(associated_codes=[],
                                          id='BAT000001',
                                          owned_codes=[],
                                          props=None,
                                          sku_id=None))
    state.teardown()
Example #2
0
def batch_patch(id):
    try:
        # must be batch patch, where json["id"] is prefixed and equals id
        json = batch_patch_schema.extend({"id": All(prefixed_id("BAT"),
                                                    id)})(request.json)
        forced = forced_schema(request.args).get("force")
    except MultipleInvalid as e:
        return problem.invalid_params_response(e)

    existing_batch = Batch.from_mongodb_doc(db.batch.find_one({"_id": id}))
    if not existing_batch:
        return problem.missing_batch_response(id)

    if json.get("sku_id"):
        existing_sku = db.sku.find_one({"_id": json['sku_id']})
        if not existing_sku:
            return problem.invalid_params_response(
                problem.missing_resource_param_error(
                    "sku_id", "must be an existing sku id"))

    if (existing_batch.sku_id and "sku_id" in json
            and existing_batch.sku_id != json["sku_id"] and not forced):
        return problem.dangerous_operation_unforced_response(
            "sku_id",
            "The sku of this batch has already been set. Can not change without force=true."
        )

    if "props" in json.keys():
        db.batch.update_one({"_id": id}, {"$set": {"props": json['props']}})
    if "name" in json.keys():
        db.batch.update_one({"_id": id}, {"$set": {"name": json['name']}})

    if "sku_id" in json.keys():
        db.batch.update_one({"_id": id}, {"$set": {"sku_id": json['sku_id']}})

    if "owned_codes" in json.keys():
        db.batch.update_one({"_id": id},
                            {"$set": {
                                "owned_codes": json['owned_codes']
                            }})
    if "associated_codes" in json.keys():
        db.batch.update_one(
            {"_id": id},
            {"$set": {
                "associated_codes": json['associated_codes']
            }})

    updated_batch = Batch.from_mongodb_doc(db.batch.find_one({"_id": id}))
    return BatchEndpoint.from_batch(updated_batch).redirect_response(False)
Example #3
0
def batch_delete(id):
    existing = Batch.from_mongodb_doc(db.batch.find_one({"_id": id}))
    if not existing:
        return problem.missing_batch_response(id)
    else:
        db.batch.delete_one({"_id": id})
        return BatchEndpoint.from_batch(existing).deleted_success_response()
Example #4
0
def batch_bins_get(id):
    resp = Response()
    existing = Batch.from_mongodb_doc(db.batch.find_one({"_id": id}))

    if not existing:
        return problem.missing_batch_response(id)
    return BatchBinsEndpoint.from_id(id, retrieve=True).get_response()
Example #5
0
def batches_post():
    try:
        json = new_batch_schema(request.json)
    except MultipleInvalid as e:
        return problem.invalid_params_response(e)

    batch = Batch.from_json(json)

    existing_batch = db.batch.find_one({"_id": batch.id})
    if existing_batch:
        return problem.duplicate_resource_response("id")

    if batch.sku_id:
        existing_sku = db.sku.find_one({"_id": batch.sku_id})
        if not existing_sku:
            return problem.invalid_params_response(
                problem.missing_resource_param_error(
                    "sku_id", "must be an existing sku id"))

    admin_increment_code("BAT", batch.id)
    db.batch.insert_one(batch.to_mongodb_doc())

    # Add text index if not yet created
    # TODO: This should probably be turned into a global flag
    if "name_text" not in db.batch.index_information().keys():
        db.sku.create_index([("name", TEXT)])

    return BatchEndpoint.from_batch(batch).created_success_response()
Example #6
0
def batch_get(id):
    existing = Batch.from_mongodb_doc(db.batch.find_one({"_id": id}))

    if not existing:
        return problem.missing_batch_response(id)
    else:
        return BatchEndpoint.from_batch(existing).get_response()
 def json_to_data_model(in_json_dict):
     if in_json_dict['id'].startswith("BIN"):
         return Bin.from_json(in_json_dict)
     if in_json_dict['id'].startswith("SKU"):
         return Sku.from_json(in_json_dict)
     if in_json_dict['id'].startswith("BAT"):
         return Batch.from_json(in_json_dict)
Example #8
0
def sku_batches_get(id):
    resp = Response()

    existing = Sku.from_mongodb_doc(db.sku.find_one({"_id": id}))
    if not existing:
        resp.status_code = 404
        resp.mimetype = "application/problem+json"
        resp.data = json.dumps({
            "type":
            "missing-resource",
            "title":
            "Can not get batches for a sku that does not exist.",
            "invalid-params": [{
                "name": "id",
                "reason": "must be an exisiting sku id"
            }]
        })
        return resp

    batches = [
        Batch.from_mongodb_doc(bson).id
        for bson in db.batch.find({"sku_id": id})
    ]
    resp.mimetype = "application/json"
    resp.data = json.dumps({"state": batches})

    return resp
    def new_batch_bad_format_owned_codes(self, data, sku_id, bad_code):
        batch = data.draw(dst.batches_(sku_id=sku_id))
        assume(batch.id not in self.model_batches.keys())

        temp_batch = Batch.from_json(batch.to_json())
        temp_batch.owned_codes.append(bad_code)
        resp = self.client.post('/api/batches', json=temp_batch.to_dict())
        assert resp.status_code == 400
        assert resp.is_json
        assert resp.json['type'] == 'validation-error'

        temp_batch = Batch.from_json(batch.to_json())
        temp_batch.associated_codes.append(bad_code)
        resp = self.client.post('/api/batches', json=temp_batch.to_dict())
        assert resp.status_code == 400
        assert resp.is_json
        assert resp.json['type'] == 'validation-error'
Example #10
0
def test_receive_batch():
    state = InventoryStateMachine()
    v1 = state.new_anonymous_batch(batch=Batch(associated_codes=[],
                                               id='BAT000000',
                                               owned_codes=[],
                                               props=None,
                                               sku_id=None))
    v2 = state.new_bin(bin=Bin(contents={}, id='BIN000000', props=None))
    state.receive_batch(batch_id=v1, bin_id=v2, quantity=1)
    state.get_existing_bin(v2)
Example #11
0
def test_update_batch():
    state = InventoryStateMachine()
    v1 = state.new_anonymous_batch(batch=Batch(associated_codes=[],
                                               id='BAT000000',
                                               owned_codes=[],
                                               props=None,
                                               sku_id=None))
    state.update_batch(batch_id=v1, patch={'owned_codes': []})
    state.get_existing_batch(batch_id=v1)
    state.teardown()
Example #12
0
 def from_batch(cls, data_batch: Batch):
     endpoint = BatchEndpoint(
         resource_uri=url_for("batch.batch_get", id=data_batch.id),
         state=data_batch.to_dict(),
         operations=[
             operations.batch_update(id),
             operations.batch_delete(id),
             operations.batch_bins(id),
         ],
     )
     endpoint.data_batch = data_batch
     return endpoint
Example #13
0
def test_delete_bin_with_batch():
    state = InventoryStateMachine()
    # state.delete_missing_bin(bin_id='BIN000000')
    v1 = state.new_anonymous_batch(batch=Batch(associated_codes=[],
                                               id='BAT000000',
                                               owned_codes=[],
                                               props=None,
                                               sku_id=None))
    v2 = state.new_bin(bin=Bin(contents={}, id='BIN000000', props=None))
    state.receive_batch(batch_id=v1, bin_id=v2, quantity=1)
    state.delete_nonempty_bin_noforce(bin_id=v2)
    state.teardown()
Example #14
0
def test_change_batch_sku():
    state = InventoryStateMachine()
    sku0 = state.new_sku(sku=Sku(id='SKU000000', name=''))
    sku1 = state.new_sku(sku=Sku(id='SKU000001', name=''))

    data = dst.DataProxy(Batch(id='BAT000000', sku_id=sku0))
    batch0 = state.new_batch_existing_sku(data=data, sku_id=sku0)

    state.attempt_update_nonanonymous_batch_sku_id(batch_id=batch0,
                                                   patch={},
                                                   sku_id=sku1)
    state.teardown()
Example #15
0
def test_was_undefined_key_error_01():
    state = InventoryStateMachine()
    v1 = state.new_bin(bin=Bin(contents={}, id='BIN000000', props={'_': None}))
    v2 = state.new_anonymous_batch(batch=Batch(associated_codes=[],
                                               id='BAT575165',
                                               name='A',
                                               owned_codes=[],
                                               props={'': None},
                                               sku_id=None))
    state.batch_locations(batch_id=v2)
    state.receive_batch(batch_id=v2, bin_id=v1, quantity=1)
    state.batch_locations(batch_id=v2)
    state.teardown()
Example #16
0
def test_new_batch_bad_format_owned_codes():
    state = InventoryStateMachine()
    v1 = state.new_sku(sku=Sku(
        associated_codes=[], id='SKU000000', name='', owned_codes=[],
        props={}))
    data = dst.DataProxy(
        Batch(associated_codes=[],
              id='BAT000000',
              name='',
              owned_codes=[],
              props={},
              sku_id='SKU000000'))
    state.new_batch_bad_format_owned_codes(bad_code='', data=data, sku_id=v1)
    state.teardown()
Example #17
0
def test_update_batch_existing_sku():
    state = InventoryStateMachine()
    v1 = state.new_sku(sku=Sku(
        associated_codes=[], id='SKU000000', name='', owned_codes=[],
        props={}))
    data = dst.DataProxy(
        Batch(associated_codes=[],
              id='BAT000000',
              name='',
              owned_codes=[],
              props={},
              sku_id='SKU000000'))
    v2 = state.new_batch_existing_sku(data=data, sku_id=v1)
    state.update_batch(batch_id=v2, patch={})
    state.teardown()
Example #18
0
def test_add_sku_to_anonymous_batch():
    state = InventoryStateMachine()
    v1 = state.new_sku(sku=Sku(associated_codes=[],
                               id='SKU000000',
                               name='',
                               owned_codes=[],
                               props=None))
    v2 = state.new_anonymous_batch(batch=Batch(associated_codes=[],
                                               id='BAT000000',
                                               owned_codes=[],
                                               props=None,
                                               sku_id=None))
    state.update_anonymous_batch_existing_sku_id(batch_id=v2,
                                                 patch={},
                                                 sku_id=v1)
    state.teardown()
Example #19
0
def test_update_batch_missing_sku():
    state = InventoryStateMachine()
    state.delete_missing_user(user_id='00')
    state.delete_missing_user(user_id=';')
    v1 = state.new_user(user={'id': '1', 'name': '', 'password': '******'})
    state.delete_missing_sku(sku_id='SKU066304')
    state.delete_missing_sku(sku_id='SKU000256')
    v2 = state.new_anonymous_batch(batch=Batch(associated_codes=[],
                                               id='BAT000000',
                                               name='',
                                               owned_codes=[],
                                               props={'a': [None]},
                                               sku_id=None))
    state.attempt_update_anonymous_batch_missing_sku_id(batch_id=v2,
                                                        patch={},
                                                        sku_id='SKU000000')
    state.teardown()
Example #20
0
def batches_(draw: DrawFn,
             id=None,
             sku_id=0,
             name=None,
             owned_codes=None,
             associated_codes=None,
             props=None):
    id = id or draw(label_("BAT"))
    if sku_id == 0:
        sku_id = draw(none(), label_("SKU"))
    name = name or draw(text("ABC"))
    owned_codes = owned_codes or draw(lists(text("abc", min_size=1)))
    associated_codes = associated_codes or draw(lists(text("abc", min_size=1)))
    props = props or draw(propertyDicts)
    return Batch(id=id,
                 sku_id=sku_id,
                 name=name,
                 owned_codes=owned_codes,
                 associated_codes=associated_codes,
                 props=props)
Example #21
0
def test_update_sku_batch():
    state = InventoryStateMachine()
    v1 = state.new_sku(sku=Sku(associated_codes=[],
                               id='SKU000001',
                               name='',
                               owned_codes=[],
                               props=None))
    v2 = state.new_sku(sku=Sku(associated_codes=[],
                               id='SKU000002',
                               name='',
                               owned_codes=[],
                               props=None))
    # state.delete_missing_sku(sku_id='SKU000000')
    data = dst.DataProxy(
        Batch(associated_codes=[],
              id='BAT000000',
              owned_codes=[],
              props={0: 0},
              sku_id='SKU000001'))
    v2 = state.new_batch_existing_sku(data=data, sku_id=v1)
    state.attempt_update_nonanonymous_batch_sku_id(batch_id=v2,
                                                   patch={},
                                                   sku_id='SKU000002')
    state.teardown()
def search():
    query = request.args['query']
    limit = getIntArgs(request.args, "limit", 20)
    startingFrom = getIntArgs(request.args, "startingFrom", 0)
    resp = Response()

    results = []

    # debug flags
    if query == '!ALL':
        results.extend([Sku.from_mongodb_doc(e) for e in db.sku.find()])
        results.extend([Batch.from_mongodb_doc(e) for e in db.batch.find()])
        results.extend([Bin.from_mongodb_doc(e) for e in db.bin.find()])
    if query == '!BINS':
        results.extend([Bin.from_mongodb_doc(e) for e in db.bin.find()])
    if query == '!SKUS':
        results.extend([Sku.from_mongodb_doc(e) for e in db.sku.find()])
    if query == '!BATCHES':
        results.extend([Batch.from_mongodb_doc(e) for e in db.batch.find()])

    # search by label
    if query.startswith('SKU'):
        results.append(Sku.from_mongodb_doc(db.sku.find_one({'_id': query})))
    if query.startswith('BIN'):
        results.append(Bin.from_mongodb_doc(db.bin.find_one({'_id': query})))
    if query.startswith('BAT'):
        results.append(
            Batch.from_mongodb_doc(db.batch.find_one({'_id': query})))
    results = [result for result in results if result != None]

    # search for skus with owned_codes
    cursor = db.sku.find({"owned_codes": query})
    for sku_doc in cursor:
        results.append(Sku.from_mongodb_doc(sku_doc))

    # search for skus with associated codes
    cursor = db.sku.find({"associated_codes": query})
    for sku_doc in cursor:
        results.append(Sku.from_mongodb_doc(sku_doc))

    # search for skus with owned_codes
    cursor = db.batch.find({"owned_codes": query})
    for batch_doc in cursor:
        results.append(Batch.from_mongodb_doc(batch_doc))

    # search for batchs with associated codes
    cursor = db.batch.find({"associated_codes": query})
    for batch_doc in cursor:
        results.append(Batch.from_mongodb_doc(batch_doc))

    # if not DEV_ENV: # maybe use global flag + env variable instead. Shouldn't need to check this every time in production/
    if "name_text" in db.sku.index_information().keys():
        cursor = db.sku.find({"$text": {"$search": query}})
        for sku_doc in cursor:
            results.append(Sku.from_mongodb_doc(sku_doc))
    if "name_text" in db.batch.index_information().keys():
        cursor = db.batch.find({"$text": {"$search": query}})
        for batch_doc in cursor:
            results.append(Batch.from_mongodb_doc(batch_doc))

    if results != []:
        paged = results[startingFrom:(startingFrom + limit)]
        resp.status_code = 200
        resp.mimetype = "application/json"
        # TODO: Add next page / prev page operations
        resp.data = json.dumps(
            {
                'state': {
                    "total_num_results": len(results),
                    "starting_from": startingFrom,
                    "limit": limit,
                    "returned_num_results": len(paged),
                    "results": paged
                },
                "operations": []
            },
            cls=Encoder)
        return resp

    resp.status_code = 200
    resp.mimetype = "application/json"
    resp.data = json.dumps(
        {
            'state': {
                "total_num_results": len(results),
                "starting_from": startingFrom,
                "limit": limit,
                "returned_num_results": 0,
                "results": []
            },
            "operations": []
        },
        cls=Encoder)
    return resp
def bin_contents_post(id):
    into_bin = Bin.from_mongodb_doc(db.bin.find_one({"_id": id}))
    item_id = request.json['id']
    quantity = request.json['quantity']
    resp = Response()
    resp.headers.add("Cache-Control", "no-cache")

    if not into_bin:
        resp.status_code = 404
        resp.mimetype = "application/problem+json"
        resp.data = json.dumps({
            "type":
            "missing-resource",
            "title":
            "Can not receive items into a bin that does not exist.",
            "invalid-params": [{
                "name": "id",
                "reason": "must be an exisiting bin id"
            }]
        })
        return resp

    if item_id.startswith("SKU"):
        exisiting_sku = Sku.from_mongodb_doc(db.sku.find_one({"_id": item_id}))
        if not exisiting_sku:
            resp.status_code = 409
            resp.mimetype = "application/problem+json"
            resp.data = json.dumps({
                "type":
                "missing-resource",
                "title":
                "Can not receive sku that does not exist.",
                "invalid-params": [{
                    "name":
                    "item_id",
                    "reason":
                    "must be an exisiting batch or sku id"
                }]
            })
            return resp
        else:
            db.bin.update_one({"_id": into_bin.id},
                              {"$inc": {
                                  f"contents.{item_id}": quantity
                              }})
            resp.status_code = 201
            return resp
    elif item_id.startswith("BAT"):
        existing_batch = Batch.from_mongodb_doc(
            db.batch.find_one({"_id": item_id}))
        if not existing_batch:
            resp.status_code = 409
            resp.mimetype = "application/problem+json"
            resp.data = json.dumps({
                "type":
                "missing-resource",
                "title":
                "Can not receive batch that does not exist.",
                "invalid-params": [{
                    "name":
                    "item_id",
                    "reason":
                    "must be an exisiting batch or sku id"
                }]
            })
            return resp
        else:
            db.bin.update_one({"_id": into_bin.id},
                              {"$inc": {
                                  f"contents.{item_id}": quantity
                              }})
            resp.status_code = 201
            return resp
    else:
        resp.status_code = 409
        resp.mimetype = "application/problem+json"
        resp.data = json.dumps({
            "type":
            "bad-id-format",
            "title":
            "Received item id must be a batch or sku.",
            "invalid-params": [{
                "name": "item_id",
                "reason": "must be an exisiting batch or sku id"
            }]
        })
        return resp
 def get_existing_batch(self, batch_id):
     rp = self.client.get(f"/api/batch/{batch_id}")
     assert rp.status_code == 200
     assert rp.is_json
     found_batch = Batch.from_json(rp.json['state'])
     assert found_batch == self.model_batches[batch_id]
def test_get_attr():
    batch = Batch(id="BAT1")
    assert hasattr(batch, "id")
    assert batch.sku_id == None