def test_price_equals_currency_matters(self): price1 = Price(currency='EUR', excl_tax=D('10.00'), tax=D('2.00')) price2 = Price(currency='USD', excl_tax=D('10.00'), tax=D('2.00')) self.assertNotEqual(price1, price2)
def handle_shipping_event(self, order, event_type, lines, line_quantities, request, response, shipment_info, **kwargs): self.validate_shipping_event(order, event_type, lines, line_quantities, **kwargs) payment_event = None group = None if event_type.name == SHIPPED: max_query = ShippingEvent.objects.all().aggregate( Max('group'))['group__max'] group = (max_query + 1) if max_query is not None else 0 self.consume_stock_allocations(order, lines, line_quantities) for line, quantity in zip(lines, line_quantities): if SHIPPED in line.shipping_event_breakdown: if line.shipping_event_breakdown[SHIPPED][ "quantity"] + quantity == line.quantity: line.set_status(SHIPPED) else: line.set_status(PARTIALLY_SHIPPED) else: if line.quantity == quantity: line.set_status(SHIPPED) else: line.set_status(PARTIALLY_SHIPPED) if all(line.status == SHIPPED for line in lines): order.set_status(SHIPPED) else: order.set_status(PARTIALLY_SHIPPED) # if they are shipping, they should have payed for shipping (at least for now).. create that payment event here.. # TODO add support here for shipping not using easypost (aka.. ignore this next section) payment_event_type = PaymentEventType._default_manager.get( code='paid_shipping') parcel_cost = shipment_info['rate'] payment_event = self._create_payment_event(order, payment_event_type, parcel_cost, lines, line_quantities, group) order.shipping_excl_tax += D(parcel_cost) order.save() shipping_event = self._create_shipping_event( order, event_type, lines, line_quantities, shipment_info, group, kwargs.get('reference', None)) designerId = ExtractDesignerIdFromOrderId(order.number) designer = TinvilleUser.objects.get(id=designerId) self._send_notifications( order, DESIGNER_PROCESSING_ORDER, { 'shop_name': Shop.objects.get(user=designer).name, 'order': order, 'order_number': get_top_level_order_number(order.number), 'tracking_number': shipment_info["tracking"], 'tracking_number_url': "https://tools.usps.com/go/TrackConfirmAction?qtc_tLabels1={0}" .format(shipment_info["tracking"]) }) # If there was a payment event created before the shipment event, attach these events if payment_event != None: payment_event.shipping_event = shipping_event payment_event.save()
def shipping_discount(self, charge): discount = charge * self.value / D('100.0') return discount.quantize(D('0.01'))
def check(): alice = Participant.from_username('alice') bob = Participant.from_username('bob') carl = Participant.from_username('carl') dana = Participant.from_username('dana') emma = Participant.from_username('emma') assert alice.giving == D('10.69') assert alice.receiving == D('5.00') assert bob.giving == D('7.00') assert bob.receiving == D('7.00') assert bob.taking == D('1.00') assert carl.giving == D('0.00') assert carl.receiving == D('0.00') assert dana.receiving == D('5.00') assert dana.npatrons == 2 assert emma.receiving == D('0.50') assert emma.npatrons == 1 funded_tips = self.db.all("SELECT amount FROM tips WHERE is_funded ORDER BY id") assert funded_tips == [3, 6, 0.5, D('1.20'), D('0.49'), 5, 2] team = Participant.from_username('team') assert team.receiving == D('1.20') assert team.npatrons == 1 team2 = Participant.from_username('team2') assert team2.receiving == D('0.49') assert team2.npatrons == 1 janet = self.janet.refetch() assert janet.giving == 0 assert janet.receiving == 0 assert janet.taking == 0 assert janet.npatrons == 0
def test_decimal_rounding(self): d = DecimalModel.create(value=D('1.2345'), value_up=D('1.2345')) d_db = DecimalModel.get(DecimalModel.id == d.id) self.assertEqual(d_db.value, D('1.23')) self.assertEqual(d_db.value_up, D('1.24'))
class IncludeGST(strategy.FixedRateTax, INRPricingPolicy): rate = D('0.18')
def create_shipping_weight_based(default_weight=D(1)): return WeightBased.objects.create( default_weight=default_weight )
def test_get_price_excl_tax_returns_correct_value(self): self.assertEqual(D('10.00'), self.stockrecord.price_excl_tax)
class ApplicationResult(object): is_final = is_successful = False fee = D('0.00') description = None class BasketFee(ApplicationResult): """ For when an offer application leads to a simple fee on the basket """ is_final = True def __init__(self, amount): self.fee = amount @property def is_successful(self): return self.fee > 0 def __str__(self): return '<Basket fee of %s>' % self.fee def __repr__(self): return '%s(%r)' % (self.__class__.__name__, self.fee) # Helper global as returning zero fee is quite common ZERO_FEE = BasketFee(D('0.00'))
def __init__(self, rec): self.username, self.route_id, self.email, fee_cap, amount = rec self.gross = D(amount) self.fee = D(0) self.fee_cap = D(fee_cap) self.net = self.gross
def setUp(self): self.product = factories.create_product() self.stockrecord = factories.create_stockrecord( self.product, price_excl_tax=D('10.00'), num_in_stock=10)
def round_(d): return d.quantize(D('0.01'), rounding=ROUND_HALF_UP)
def test_dues16_reduction(self): """ test the dues16_reduction functionality """ # have to accept their membersip first m1 = C3sMember.get_by_id(1) # german normal member m1.membership_accepted = True m2 = C3sMember.get_by_id(2) # english normal member m2.membership_accepted = True self.config.add_route('make_dues16_invoice_no_pdf', '/') self.config.add_route('make_dues16_reversal_invoice_pdf', '/') self.config.add_route('detail', '/detail/') self.config.add_route('error_page', '/error_page') self.config.add_route('toolbox', '/toolbox') req = testing.DummyRequest() req.referrer = 'toolbox' from c3smembership.views.membership_dues_2016 import ( send_dues16_invoice_batch, ) # send out invoices. this is a prerequisite for reductions res = send_dues16_invoice_batch(req) res """ test reduction of dues """ # pre-check self.assertFalse(m1.dues16_reduced) # not reduced yet! _m1_amount_reduced = m1.dues16_amount_reduced # is Decimal('0') _number_of_invoices_before_reduction = len(Dues16Invoice.get_all()) # print("_number_of_invoices_before_reduction: {}".format( # _number_of_invoices_before_reduction)) # we have 2 invoices as of now self.assertEqual(len(Dues16Invoice.get_all()), 2) # import the function under test from c3smembership.views.membership_dues_2016 import dues16_reduction ############################################################# # try to reduce to the given calculated amount (edge case coverage) # this will not work, produce no new invoices req_reduce = testing.DummyRequest( # prepare request post={ 'confirmed': 'yes', 'submit': True, 'amount': 50, }, ) req_reduce.matchdict['member_id'] = 1 # do it for member with id 1 res_reduce = dues16_reduction(req_reduce) # call reduce on her self.assertEqual(len(Dues16Invoice.get_all()), 2) # no new invoice ############################################################# # try to reduce above the given calculated amount # this will not work, produce no new invoices req_reduce = testing.DummyRequest( # prepare request post={ 'confirmed': 'yes', 'submit': True, 'amount': 500, }, ) req_reduce.matchdict['member_id'] = 1 # do it for member with id 1 res_reduce = dues16_reduction(req_reduce) # call reduce on her self.assertEqual(len(Dues16Invoice.get_all()), 2) # no new invoice ############################################################# # valid reduction but without confirmation req_reduce = testing.DummyRequest(post={ 'confirmed': 'no', 'submit': True, 'amount': 42, }, ) req_reduce.matchdict['member_id'] = 1 res_reduce = dues16_reduction(req_reduce) self.assertEqual(len(Dues16Invoice.get_all()), 2) # no new invoice ############################################################# # valid reduction req_reduce = testing.DummyRequest(post={ 'confirmed': 'yes', 'submit': True, 'amount': 42, }, ) req_reduce.matchdict['member_id'] = 1 res_reduce = dues16_reduction(req_reduce) _number_of_invoices_after_reduction = len(Dues16Invoice.get_all()) assert ( # two new invoices must have been issued (_number_of_invoices_before_reduction + 2) == _number_of_invoices_after_reduction) assert (_number_of_invoices_after_reduction == 4) assert ('detail' in res_reduce.headers['Location']) # 302 to detail p. assert (_m1_amount_reduced != m1.dues16_amount_reduced) # changed! assert (m1.dues16_amount_reduced == 42) # changed to 42! # check the invoice created _rev_inv = Dues16Invoice.get_by_invoice_no( _number_of_invoices_before_reduction + 1) _new_inv = Dues16Invoice.get_by_invoice_no( _number_of_invoices_before_reduction + 2) # print(_rev_inv.invoice_amount) # print(type(_rev_inv.invoice_amount)) assert (_rev_inv.invoice_amount == D('-50')) assert (_new_inv.invoice_amount == D('42')) # we have 4 invoices as of now self.assertEqual(len(Dues16Invoice.get_all()), 4) ############################################################# # now try to raise above the previous reduction req_reduce = testing.DummyRequest(post={ 'confirmed': 'yes', 'submit': True, 'amount': 50, }, ) req_reduce.matchdict['member_id'] = 1 res_reduce = dues16_reduction(req_reduce) _number_of_invoices_after_reduction = len(Dues16Invoice.get_all()) # no new invoices were created, we still have 4 invoices self.assertEqual(len(Dues16Invoice.get_all()), 4) ############################################################# # try to reduce to the same amount again (edge case coverage) req_reduce = testing.DummyRequest( post={ 'confirmed': 'yes', 'submit': True, 'amount': 42, # lots of values missing }, ) req_reduce.matchdict['member_id'] = 1 res_reduce = dues16_reduction(req_reduce) ############################################################# # try to reduce to zero (edge case coverage) # print("------------- reduction to zero ahead!!!") req_reduce = testing.DummyRequest( post={ 'confirmed': 'yes', 'submit': True, 'amount': 0, # lots of values missing }, ) req_reduce.matchdict['member_id'] = 1 res_reduce = dues16_reduction(req_reduce) req_reduce = testing.DummyRequest( post={ 'confirmed': 'yes', 'submit': True, 'amount': 0, # lots of values missing }, ) req_reduce.matchdict['member_id'] = 2 res_reduce = dues16_reduction(req_reduce) ############################################################# # try to reduce to zero with english member (edge case coverage) # how to do this if you already reduced to zero? reduce to more first! req_reduce = testing.DummyRequest( post={ 'confirmed': 'yes', 'submit': True, 'amount': 1, # lots of values missing }, ) req_reduce.matchdict['member_id'] = 1 res_reduce = dues16_reduction(req_reduce) m1.locale = u'en' req_reduce = testing.DummyRequest( post={ 'confirmed': 'yes', 'submit': True, 'amount': 0, # lots of values missing }, ) req_reduce.matchdict['member_id'] = 1 res_reduce = dues16_reduction(req_reduce) ############################################################# """ test reversal invoice PDF generation """ from c3smembership.views.membership_dues_2016 import ( make_dues16_reversal_invoice_pdf) req2 = testing.DummyRequest() # wrong token: must fail! req2.matchdict = { 'email': m1.email, 'code': m1.dues16_token + 'false!!!', # must fail 'no': u'0006', } res = make_dues16_reversal_invoice_pdf(req2) assert ('application/pdf' not in res.headers['Content-Type']) # no PDF assert ('error_page' in res.headers['Location']) # but error # wrong invoice number: must fail! req2.matchdict = { 'email': m1.email, 'code': m1.dues16_token, 'no': u'1234', # must fail } res = make_dues16_reversal_invoice_pdf(req2) assert ('application/pdf' not in res.headers['Content-Type']) # no PDF assert ('error_page' in res.headers['Location']) # but error # wrong invoice token: must fail! i2 = Dues16Invoice.get_by_invoice_no('2') i2.token = u'not_matching' req2.matchdict = { 'email': m2.email, 'code': m2.dues16_token, 'no': u'2', # must fail } res = make_dues16_reversal_invoice_pdf(req2) assert ('application/pdf' not in res.headers['Content-Type']) # no PDF assert ('error_page' in res.headers['Location']) # but error ###################################################################### # wrong invoice type (not a reversal): must fail! (edge case coverage) assert (not i2.is_reversal) # i2 is not a reversal i2.token = m2.dues16_token # we give it a valid token req2.matchdict = { 'email': m2.email, 'code': m2.dues16_token, 'no': u'0002', } res = make_dues16_reversal_invoice_pdf(req2) assert ('application/pdf' not in res.headers['Content-Type']) # no PDF assert ('error_page' in res.headers['Location']) # but error ###################################################################### # retry with valid token: req2.matchdict = { 'email': m1.email, 'code': m1.dues16_token, 'no': u'0003', } res = make_dues16_reversal_invoice_pdf(req2) # print("length of the result: {}".format(len(res.body))) # print("headers of the result: {}".format((res.headers))) assert (60000 < len(res.body) < 80000) assert ('application/pdf' in res.headers['Content-Type'])
def test_can_be_instantiated_with_tax_amount(self): price = Price('USD', D('10.00'), tax=D('2.00')) self.assertTrue(price.is_tax_known) self.assertEqual(D('12.00'), price.incl_tax)
def test_free_product_is_available_to_buy(self): product = factories.create_product(price=D('0'), num_in_stock=1) info = self.strategy.fetch_for_product(product) self.assertTrue(info.availability.is_available_to_buy) self.assertTrue(info.price.exists)
class ApplicationResult(object): is_final = is_successful = False fee = D('0.00') description = None
def test_specifies_product_has_correct_price(self): self.assertEqual(D('10.00'), self.info.price.incl_tax)
def test_success_response_creates_model(self): txn = Transaction.objects.get(correlation_id='50a8d895e928f') self.assertEqual(D('10.00'), txn.amount) self.assertEqual('GBP', txn.currency) self.assertEqual('Success', txn.ack) self.assertEqual('EC-6469953681606921P', txn.token)
def test_decimals(self): # check that Decimal instances that have different representations # but equal values give the same hash zeros = ['0', '-0', '0.0', '-0.0e10', '000e-10'] for zero in zeros: self.check_equal_hash(D(zero), D(0)) self.check_equal_hash(D('1.00'), D(1)) self.check_equal_hash(D('1.00000'), D(1)) self.check_equal_hash(D('-1.00'), D(-1)) self.check_equal_hash(D('-1.00000'), D(-1)) self.check_equal_hash(D('123e2'), D(12300)) self.check_equal_hash(D('1230e1'), D(12300)) self.check_equal_hash(D('12300'), D(12300)) self.check_equal_hash(D('12300.0'), D(12300)) self.check_equal_hash(D('12300.00'), D(12300)) self.check_equal_hash(D('12300.000'), D(12300))
def test_close_raises_for_unknown_disbursement_strategy(self): alice = self.make_participant('alice', balance=D('0.00')) with pytest.raises(alice.UnknownDisbursementStrategy): alice.close('cheese')
def test_update_cached_amounts(self): team = self.make_participant('team', kind='group') alice = self.make_participant('alice', balance=100) bob = self.make_participant('bob') carl = self.make_participant('carl', balance=1.56) dana = self.make_participant('dana') emma = Participant.make_stub(username='******') team2 = self.make_participant('team2', kind='group') team2.add_member(dana) alice.set_tip_to(dana, '3.00') alice.set_tip_to(bob, '6.00') alice.set_tip_to(emma, '0.50') alice.set_tip_to(team, '1.20') alice.set_tip_to(team2, '0.49') bob.set_tip_to(alice, '5.00') team.add_member(bob) team.set_take_for(bob, D('1.00'), team) bob.set_tip_to(dana, '2.00') # funded by bob's take bob.set_tip_to(emma, '7.00') # not funded, insufficient receiving carl.set_tip_to(dana, '2.08') # not funded, insufficient balance def check(): alice = Participant.from_username('alice') bob = Participant.from_username('bob') carl = Participant.from_username('carl') dana = Participant.from_username('dana') emma = Participant.from_username('emma') assert alice.giving == D('10.69') assert alice.receiving == D('5.00') assert bob.giving == D('7.00') assert bob.receiving == D('7.00') assert bob.taking == D('1.00') assert carl.giving == D('0.00') assert carl.receiving == D('0.00') assert dana.receiving == D('5.00') assert dana.npatrons == 2 assert emma.receiving == D('0.50') assert emma.npatrons == 1 funded_tips = self.db.all("SELECT amount FROM tips WHERE is_funded ORDER BY id") assert funded_tips == [3, 6, 0.5, D('1.20'), D('0.49'), 5, 2] team = Participant.from_username('team') assert team.receiving == D('1.20') assert team.npatrons == 1 team2 = Participant.from_username('team2') assert team2.receiving == D('0.49') assert team2.npatrons == 1 janet = self.janet.refetch() assert janet.giving == 0 assert janet.receiving == 0 assert janet.taking == 0 assert janet.npatrons == 0 # Pre-test check check() # Check that update_cached_amounts doesn't mess anything up Payday.start().update_cached_amounts() check() # Check that update_cached_amounts actually updates amounts self.db.run(""" UPDATE tips t SET is_funded = true FROM participants p WHERE p.id = t.tippee AND p.mangopay_user_id IS NOT NULL; UPDATE participants SET giving = 10000 , taking = 10000 WHERE mangopay_user_id IS NOT NULL; UPDATE participants SET npatrons = 10000 , receiving = 10000 WHERE status = 'active'; """) Payday.start().update_cached_amounts() check() # Check that the update methods of Participant concur for p in self.db.all("SELECT p.*::participants FROM participants p"): p.update_receiving() p.update_giving() check()
def test_wbtba_raises_NotWhitelisted_if_not_whitelisted(self): alice = self.make_participant('alice', balance=D('10.00')) with self.db.get_cursor() as cursor: with pytest.raises(NotWhitelisted): alice.withdraw_balance_to_bank_account(cursor)
def test_decimal_field(self): d1 = DecimalModel.create(value=D('3')) d2 = DecimalModel.create(value=D('100.33')) self.assertEqual(sorted(d.value for d in DecimalModel.select()), [D('3'), D('100.33')])
def place_order( self, basket, total, # noqa (too complex (12)) shipping_method, shipping_charge, user=None, shipping_address=None, billing_address=None, order_number=None, status=None, request=None, **kwargs): """ Placing an order involves creating all the relevant models based on the basket and session data. 下订单涉及根据购物篮和会话数据创建所有相关模型。 """ if basket.is_empty: raise ValueError(_("Empty baskets cannot be submitted")) if not order_number: generator = OrderNumberGenerator() order_number = generator.order_number(basket) if not status and hasattr(settings, 'OSCAR_INITIAL_ORDER_STATUS'): status = getattr(settings, 'OSCAR_INITIAL_ORDER_STATUS') if Order._default_manager.filter(number=order_number).exists(): raise ValueError( _("There is already an order with number %s") % order_number) with transaction.atomic(): # Ok - everything seems to be in order, let's place the order # 好的 - 一切似乎都井然有序,让我们下订单 order = self.create_order_model(user, basket, shipping_address, shipping_method, shipping_charge, billing_address, total, order_number, status, request, **kwargs) for line in basket.all_lines(): self.create_line_models(order, line) self.update_stock_records(line) for voucher in basket.vouchers.select_for_update(): available_to_user, msg = voucher.is_available_to_user( user=user) if not voucher.is_active() or not available_to_user: raise ValueError(msg) # Record any discounts associated with this order # 记录与此订单相关的任何折扣 for application in basket.offer_applications: # Trigger any deferred benefits from offers and capture the # resulting message # 触发优惠中的任何延期优惠并捕获生成的消息 application['message'] \ = application['offer'].apply_deferred_benefit(basket, order, application) # Record offer application results # 记录报价申请结果 if application['result'].affects_shipping: # Skip zero shipping discounts # 跳过零运费折扣 shipping_discount = shipping_method.discount(basket) if shipping_discount <= D('0.00'): continue # If a shipping offer, we need to grab the actual discount off # the shipping method instance, which should be wrapped in an # OfferDiscount instance. # 如果是运费报价,我们需要从运输方法实例中获取实际折扣,该实例 # 应包含在OfferDiscount实例中。 application['discount'] = shipping_discount self.create_discount_model(order, application) self.record_discount(application) for voucher in basket.vouchers.all(): self.record_voucher_usage(order, voucher, user) # Send signal for analytics to pick up # 发送分析信号 ? order_placed.send(sender=self, order=order, user=user) return order
def total_discount_excl_tax(self): discount = D('0.00') for line in self.lines.all(): discount += line.discount_excl_tax return discount
(1.1 + 2.2) == 3.3 # out put: False print( 1.1 + 2.2 ) # out put 3.300000003 import decimal print(0.1) print(decimal.Decimal(0.1)) from decimal import Decimal #Out put: 3.3 print(Decimal('1.1') + Decimal('2.2')) from decimal import Decimal as D print(D('1.1') + D('2.2')) # Phân số import fractions print(fractions.Fraction(4.5)) print(fractions.Fraction(2,5)) # Tạo phân số từ một float thì nên đưa vào một string print(fractions.Fraction('0.1')) #Toán học trong python from fractions import Fraction as F import math print(math.pi)
def shipping_discount(self, charge): if charge < self.value: return D('0.00') return charge - self.value
def test_one_stockrecord(self): product = factories.create_product(price=D('1.99'), num_in_stock=4) info = self.strategy.fetch_for_product(product) self.assertTrue(info.availability.is_available_to_buy) self.assertEqual(D('1.99'), info.price.excl_tax) self.assertEqual(D('1.99'), info.price.incl_tax)
def test_amount_is_saved(self): self.assertEqual(D('33.98'), self.txn.amount)
def test_price_equals_formats(self): price1 = Price(currency='USD', excl_tax=D('10.00'), tax=D('2.00')) price2 = Price(currency='USD', excl_tax=D('10.00'), incl_tax=D('12.00')) self.assertEqual(price1, price2)