def test_prefers_current_stock_batches_to_shipments(): in_stock_batch = Batch("in-stock-batch", "RETRO-CLOCK", 100, eta=None) shipment_batch = Batch("shipment-batch", "RETRO-CLOCK", 100, eta=tomorrow) line = OrderLine("oref", "RETRO-CLOCK", 10) allocate(line, [in_stock_batch, shipment_batch]) assert in_stock_batch.available_quantity == 90 assert shipment_batch.available_quantity == 100
def test_allocate_prefers_warehouse(): batch_warehouse = Batch(sku="SMALL-TABLE", qty=20) batch_shipping = Batch(sku="SMALL-TABLE", qty=20, eta=10) order_line = OrderLine(ref="bla", sku="SMALL-TABLE", qty=20) allocate(order_line, [batch_shipping, batch_warehouse]) assert batch_warehouse.qty == 0 assert batch_shipping.qty == 20
def test_allocating_to_batch_reduces_availability(): batch = Batch("batch-001", "SMALL-TABLE", qty=20, eta=datetime.date.today()) line = OrderLine('order-ref', "SMALL-TABLE", 2) batch.allocate(line) assert batch.available_quantity == 18
def test_prefers_earlier_batches(): earliest = Batch('speedy-batch', 'MINIMALIST-SPOON', 100, eta=today) medium = Batch("normal-batch", 'MINIMALIST-SPOON', 100, eta=tomorrow) latest = Batch("slow-batch", "MINIMALIST-SPOON", 100, eta=later) line = OrderLine("order1", "MINIMALIST-SPOON", 10) allocate(line, [medium, earliest, latest]) assert earliest.available_quantity == 90 assert medium.available_quantity == 100 assert latest.available_quantity == 100
def test_allocating_in_stock_over_shipment(): in_stock_batch = Batch('in-stock-batch', 'CLOCK', 100, eta=None) shipment_batch = Batch("shipment-batch", "CLOCK", 100, eta=tomorrow) line = OrderLine("oref", "CLOCK", 10) allocate(line, [in_stock_batch, shipment_batch]) assert in_stock_batch.available_quantity == 90 assert shipment_batch.available_quantity == 100
def test_allocate_quickest_warehouse(): batch_warehouse_slow = Batch(sku="SMALL-TABLE", qty=20, eta=10) batch_shipping_unavaiable = Batch(sku="SMALL-TABLE", qty=2, eta=1) batch_shipping_ok = Batch(sku="SMALL-TABLE", qty=20, eta=5) order_line = OrderLine(ref="bla", sku="SMALL-TABLE", qty=20) allocate( order_line, [batch_warehouse_slow, batch_shipping_unavaiable, batch_shipping_ok] ) assert batch_warehouse_slow.qty == 20 assert batch_shipping_unavaiable.qty == 2 assert batch_shipping_ok.qty == 0
def test_returns_allocated_batch_ref(): in_stock_batch = Batch("in-stock-batch-ref", "HIGHBROW-POSTER", 100, eta=None) shipment_batch = Batch("shipment-batch-ref", "HIGHBROW-POSTER", 100, eta=tomorrow) line = OrderLine("oref", "HIGHBROW-POSTER", 10) allocation = allocate(line, [in_stock_batch, shipment_batch]) assert allocation == in_stock_batch.reference
def test_OrderLine(self): from PIL import Image from StringIO import StringIO from django.core.files.base import File def get_image_file(name='test.png', ext='png', size=(50, 50), color=(256, 0, 0)): file_obj = StringIO() image = Image.new("RGBA", size=size, color=color) image.save(file_obj, ext) file_obj.seek(0) return File(file_obj, name=name) def add_cat(name): c = Category.objects.get_or_create(catName=name)[0] return c def add_product(cat, name, description, price, stock): from django.core.files import File products = Product.objects.filter(prodName=name) if products.exists(): p = products[0] p.delete() p = Product.objects.get_or_create(category=cat, prodName=name, description=description, price=price, stock=stock, image=get_image_file())[0] return p units5 = 5 cat = add_cat("cat_1") product = add_product(cat, "prod_1", "descript_1", 1, 2) order = self.createOrder() orderline = OrderLine(order=order, product=product, pricePerUnit=product.price, units=units5) orderline.save() self.assertEqual(order.orderLines.first(), orderline) #N->1 relationship self.assertEqual(orderline.product, product) self.assertEqual(orderline.pricePerUnit, product.price) self.assertEqual(orderline.units, units5) self.assertEqual(orderline.getProductCost(), orderline.pricePerUnit * orderline.units) self.assertEqual(order.getTotalCost(), orderline.getProductCost())
def generate_fake_data(): fake = Faker('es_ES') fake.add_provider(PhoneNumberProvider) for _ in range(100): pass new_fake_client = Client() new_fake_client.name = fake.name() new_fake_client.address = fake.address() new_fake_client.id_city = random.randint(1, 3) new_fake_client.telephone_number = fake.phone_number() new_fake_client.active = 1 db.session.add(new_fake_client) for _ in range(100): new_fake_order = Order() new_fake_order.id_client = random.randint(1, 99) new_fake_order.date = fake.date_between_dates( date_start=datetime(2021, 1, 1), date_end=datetime(2021, 2, 26)).isoformat() new_fake_order.address = fake.address() new_fake_order.current_status = Order.DELIVERED_STATUS new_fake_order.is_delivery = random.randint(0, 1) == 1 new_fake_order.telephone_number = fake.phone_number() text = fake.text() new_fake_order.observations = (text[:255]) if len(text) > 255 else text new_order_line = OrderLine() new_order_line.id_product = 2 new_order_line.quantity = 1 new_order_line.unitary_price = 210 new_order_line.total_price = 210 new_fake_order.order_lines.append(new_order_line) db.session.add(new_fake_order) db.session.commit()
def make_batch_and_line(sku,batch_qty,line_qty): return ( Batch("batch-001",sku,batch_qty,eta=date.today()), OrderLine("order-123",sku,line_qty) )
def test_allocate_line_with_other_product_raises_product_mismatch( batch, other_product): order_line = OrderLine('1', other_product, 10) with pytest.raises(ProductMismatch): batch.allocate(order_line)
def test_allocation(): batch = Batch(sku="SMALL-TABLE", qty=20) order_line = OrderLine(sku="SMALL-TABLE", qty=2, ref="some order") allocate(order_line, batch) assert batch.qty == 18
def test_allocation_not_enough(): batch = Batch(sku="BLUE-CUSHION", qty=1) order_line = OrderLine(sku="BLUE-CUSHION", qty=2, ref="some order") allocate(order_line, batch) assert batch.qty == 1
def test_cant_allocate_twice(): batch = Batch(sku="SMALL-TABLE", qty=20) order_line = OrderLine(ref="some orderline", sku="SMALL-TABLE", qty=2) allocate(order_line, batch) allocate(order_line, batch) assert batch.qty == 18
def test_allocate_line_greater_than_available_qty_raises_unavailable_quantity( batch, product): order_line = OrderLine('1', product, 22) with pytest.raises(UnavailableQuantity): batch.allocate(order_line)
def test_raises_out_of_stock_exception_if_cannot_allocate(): batch = Batch('batch1', 'SMALL-FORK', 10, eta=today) allocate(OrderLine('order1', 'SMALL-FORK', 10), [batch]) with pytest.raises(OutOfStock, match='SMALL-FORK'): allocate(OrderLine('order2', 'SMALL-FORK', 1), [batch])
def checkout(request): if not request.session.has_key("basket"): return redirect("category_list") elif request.GET.has_key("add_item"): item = Item.objects.get(pk=request.GET["add_item"]) match = 0 for itm in request.session["basket"]: if itm["item"] == item: itm["amount"] += 1 match = 1 if match == 0: request.session["basket"].append({'item': item, 'amount': 1}) request.session.modified = True return redirect("checkout") elif request.GET.has_key("remove_item"): item = Item.objects.get(pk=request.GET["remove_item"]) for itm in request.session["basket"]: if itm["item"] == item: itm["amount"] -= 1 if itm["amount"] == 0: request.session["basket"].remove(itm) if request.session["basket"] == []: del request.session["basket"] request.session.modified = True return redirect("checkout") basket = request.session["basket"] or [] total = 0 itms = [] for itm in basket: itm["price"] = (itm["item"].price * itm["amount"]) itm["fees"] = [] itms.append(itm["item"]) total = total + itm["price"] for fee in itm["item"].extra_fees.all(): d = {'fee': fee, 'price': (fee.price * itm["amount"])} itm["fees"].append(d) total = total + d["price"] # Add eventual fees to order for orderfee in OrderFee.objects.filter( applies_below__gt=total).order_by('price'): avoid = False avoid_item = None diff = (orderfee.applies_below - total) total = total + orderfee.price print diff if diff < 150 and diff > 0: try: avoid_item = Item.objects.filter(price__gte=(diff), price__lte=(diff + 30)) if avoid_item.filter(related_items__in=itms).count() > 0: avoid_item = avoid_item.filter(related_items__in=itms) avoid_item = avoid_item[random.randrange( 0, avoid_item.count())] avoid = True except: pass if diff > 0: basket.append({ 'price': orderfee.price, 'amount': 1, 'name': orderfee.name, 'avoid': avoid, 'avoid_fee': diff, 'avoid_item': avoid_item, 'item': None, }) if request.POST: form = OrderForm(request.POST, instance=Order(site=Site.objects.get_current())) if form.is_valid(): order = form.save() for itm in basket: if itm["item"]: o = OrderLine(item_id=itm["item"].id, name=itm["item"].name, amount=itm["amount"], price=itm["item"].price, order=order) o.save() i = Item.objects.get(pk=itm["item"].id) i.amount_on_stock -= itm["amount"] i.amount_sold += itm["amount"] i.save() for fee in itm["item"].extra_fees.all(): o = OrderLine(fee_id=fee.id, name=fee.name, amount=itm["amount"], price=fee.price, order=order) o.save() else: o = OrderLine(name=itm["name"], amount=itm["amount"], price=itm["price"], order=order) o.save() msg = render_to_string("catalog/order_confirmation.html", { 'order': order, 'site': Site.objects.get_current(), }) OrderMessage(order=order, gateway=default_settings.MSG_GATEWAY_DEFAULT, message=msg).save() request.session.flush() if request.POST.has_key("remember_my_address"): request.session["first_name"] = order.first_name request.session["last_name"] = order.last_name request.session["address"] = order.address request.session["address_2"] = order.address_2 request.session["postal_code"] = order.postal_code request.session["city"] = order.city request.session["cellphone"] = order.cellphone request.session["email"] = order.email request.session["remember_my_address"] = request.POST[ "remember_my_address"] if options.payment == True: return redirect("pay", order_id=order.id) return redirect(order) else: form = OrderForm(initial=request.session) dictionary = { 'basket': basket, 'total': total, 'vat': total * Decimal("0.2"), 'form': form, } return render_to_response('catalog/checkout.html', dictionary, context_instance=RequestContext(request))
def test_matching_in_allocation(): batch = Batch('Batch-03', 'Nails', qty=50, eta=datetime.date.today()) line = OrderLine('R-32', 'Wood', qty=3) batch.can_allocate(line) is False
def checkout(request): if not request.session.has_key("basket"): return redirect("category_list") elif request.GET.has_key("add_item"): item = Item.objects.get(pk=request.GET["add_item"]) match = 0 for itm in request.session["basket"]: if itm["item"] == item: itm["amount"] += 1 match = 1 if match == 0: request.session["basket"].append({'item': item, 'amount': 1}) request.session.modified = True return redirect("checkout") elif request.GET.has_key("remove_item"): item = Item.objects.get(pk=request.GET["remove_item"]) for itm in request.session["basket"]: if itm["item"] == item: itm["amount"] -= 1 if itm["amount"] == 0: request.session["basket"].remove(itm) if request.session["basket"] == []: del request.session["basket"] request.session.modified = True return redirect("checkout") basket = request.session["basket"] or [] total = 0 itms = [] for itm in basket: itm["price"] = (itm["item"].price * itm["amount"]) itm["fees"] = [] itms.append(itm["item"]) total = total + itm["price"] for fee in itm["item"].extra_fees.all(): d = { 'fee': fee, 'price': (fee.price * itm["amount"]) } itm["fees"].append(d) total = total + d["price"] # Add eventual fees to order for orderfee in OrderFee.objects.filter(applies_below__gt=total).order_by('price'): avoid = False avoid_item = None diff = (orderfee.applies_below - total) total = total + orderfee.price print diff if diff < 150 and diff > 0: try: avoid_item = Item.objects.filter(price__gte=(diff), price__lte=(diff+30)) if avoid_item.filter(related_items__in=itms).count() > 0: avoid_item = avoid_item.filter(related_items__in=itms) avoid_item = avoid_item[random.randrange(0,avoid_item.count())] avoid = True except: pass if diff > 0: basket.append({ 'price': orderfee.price, 'amount': 1, 'name': orderfee.name, 'avoid': avoid, 'avoid_fee': diff, 'avoid_item': avoid_item, 'item': None, }) if request.POST: form = OrderForm(request.POST, instance=Order(site=Site.objects.get_current())) if form.is_valid(): order = form.save() for itm in basket: if itm["item"]: o = OrderLine(item_id=itm["item"].id, name=itm["item"].name, amount=itm["amount"], price=itm["item"].price, order=order) o.save() i = Item.objects.get(pk=itm["item"].id) i.amount_on_stock -= itm["amount"] i.amount_sold += itm["amount"] i.save() for fee in itm["item"].extra_fees.all(): o = OrderLine(fee_id=fee.id, name=fee.name, amount=itm["amount"], price=fee.price, order=order) o.save() else: o = OrderLine(name=itm["name"], amount=itm["amount"], price=itm["price"], order=order) o.save() msg = render_to_string("catalog/order_confirmation.html", { 'order': order, 'site': Site.objects.get_current(), }) OrderMessage(order=order, gateway=default_settings.MSG_GATEWAY_DEFAULT, message=msg).save() request.session.flush() if request.POST.has_key("remember_my_address"): request.session["first_name"] = order.first_name request.session["last_name"] = order.last_name request.session["address"] = order.address request.session["address_2"] = order.address_2 request.session["postal_code"] = order.postal_code request.session["city"] = order.city request.session["cellphone"] = order.cellphone request.session["email"] = order.email request.session["remember_my_address"] = request.POST["remember_my_address"] if options.payment == True: return redirect("pay", order_id=order.id) return redirect(order) else: form = OrderForm(initial=request.session) dictionary = { 'basket': basket, 'total': total, 'vat': total * Decimal("0.2"), 'form': form, } return render_to_response('catalog/checkout.html', dictionary, context_instance=RequestContext(request))
def order_line(product): return OrderLine('1', product, 10)
def test_cannot_allocate_if_skus_do_not_match(): batch=Batch("batch-001","UNCONFORTABLE-CHARE",100,eta=None) different_sku_line=OrderLine("order-123","EXPENIVE-TOASTER",10) assert batch.can_allocate(different_sku_line) is False