def _create_payment(self): group = PaymentGroup() group.payer = self.client.person method = PaymentMethod.get_by_name(self.store, u'credit') branch = api.get_current_branch(self.store) if self.model.value < 0: payment_type = Payment.TYPE_IN else: payment_type = Payment.TYPE_OUT # Set status to PENDING now, to avoid calling set_pending on # on_confirm for payments that shoud not have its status changed. payment = Payment(open_date=localtoday(), branch=branch, status=Payment.STATUS_PENDING, description=self.model.description, value=abs(self.model.value), base_value=abs(self.model.value), due_date=localtoday(), method=method, group=group, till=None, category=None, payment_type=payment_type, bill_received=False) payment.pay() return payment
def _create_payment(self): group = PaymentGroup() group.payer = self.client.person method = PaymentMethod.get_by_name(self.store, u'credit') branch = api.get_current_branch(self.store) if self.model.value < 0: payment_type = Payment.TYPE_IN else: payment_type = Payment.TYPE_OUT # Set status to PENDING now, to avoid calling set_pending on # on_confirm for payments that shoud not have its status changed. payment = Payment(open_date=localtoday(), branch=branch, status=Payment.STATUS_PENDING, description=self.model.description, value=abs(self.model.value), base_value=abs(self.model.value), due_date=localtoday(), method=method, group=group, category=None, payment_type=payment_type, bill_received=False) payment.pay() return payment
def on_confirm(self): self.model.base_value = self.model.value facet = self.person.read() if facet and facet is not ValueUnset: setattr(self.model.group, self.person_attribute, facet.person) self.model.attachment = self.fields['attachment'].attachment # We can only change the identifier if the object is branch new (not edit_mode). If the # object is being edited and the identifier is not temporary, it has already being synced # with the destination branch and the identifier should no longer change. # XXX: We can probably remove the temporary identifiers now that we have the station_id as # part of the key in the identifiable domain. other_branch = self._is_for_another_branch() if other_branch and not self.edit_mode: self.model.identifier = Payment.get_temporary_identifier( self.store) self.store.add(self.model.group) self.store.add(self.model) if self.repeat.get_selected() != _ONCE: Payment.create_repeated(self.store, self.model, self.repeat.get_selected(), self.model.due_date.date(), self.end_date.get_date(), temporary_identifiers=other_branch)
def on_confirm(self): self.model.base_value = self.model.value facet = self.person.read() if facet and facet is not ValueUnset: setattr(self.model.group, self.person_attribute, facet.person) self.model.attachment = self.fields['attachment'].attachment # We can only change the identifier if the object is branch new (not edit_mode). If the # object is being edited and the identifier is not temporary, it has already being synced # with the destination branch and the identifier should no longer change. # XXX: We can probably remove the temporary identifiers now that we have the station_id as # part of the key in the identifiable domain. other_branch = self._is_for_another_branch() if other_branch and not self.edit_mode: self.model.identifier = Payment.get_temporary_identifier(self.store) self.store.add(self.model.group) self.store.add(self.model) if self.repeat.get_selected() != _ONCE: Payment.create_repeated(self.store, self.model, self.repeat.get_selected(), self.model.due_date.date(), self.end_date.get_date(), temporary_identifiers=other_branch)
def test_get_open_date_string(self): method = PaymentMethod.get_by_name(self.store, u'check') payment = Payment(value=currency(100), branch=self.create_branch(), due_date=localnow(), method=method, group=None, till=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store) self.assertNotEqual(payment.get_open_date_string(), u"")
def testGetOpenDateString(self): method = PaymentMethod.get_by_name(self.store, u'check') payment = Payment(value=currency(100), branch=self.create_branch(), due_date=localnow(), method=method, group=None, till=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store) self.assertNotEqual(payment.get_open_date_string(), u"")
def test_get_penalty(self): method = PaymentMethod.get_by_name(self.store, u'check') payment = Payment(value=currency(100), branch=self.create_branch(), station=self.current_station, due_date=localnow(), method=method, group=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store) for day, expected_value in [(0, 0), (-1, 0), (-30, 0), (30, 0)]: payment.due_date = self._get_relative_day(day) self.assertEqual(payment.get_penalty(), currency(expected_value)) method.penalty = Decimal(20) for day, expected_value in [(0, 0), (-1, 20), (-30, 20), (30, 0)]: payment.due_date = self._get_relative_day(day) self.assertEqual(payment.get_penalty(), currency(expected_value)) due_date = self._get_relative_day(-15) paid_date = self._get_relative_day(-5) payment.due_date = payment.open_date = due_date self.assertEqual(payment.get_penalty(paid_date.date()), currency(20)) self.assertEqual(payment.get_penalty(due_date.date()), currency(0)) for day in (18, -18): paid_date = self._get_relative_day(day) self.assertRaises(ValueError, payment.get_penalty, paid_date.date())
def test_new(self): with self.assertRaises(TypeError): Payment(due_date=localnow(), branch=self.create_branch(), payment_type=Payment.TYPE_OUT, store=self.store) payment = Payment(value=currency(10), due_date=localnow(), branch=self.create_branch(), method=None, group=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store) self.assertTrue(payment.status == Payment.STATUS_PREVIEW)
def on_confirm(self): self.model.base_value = self.model.value facet = self.person.read() if facet and facet is not ValueUnset: setattr(self.model.group, self.person_attribute, facet.person) self.model.attachment = self.fields['attachment'].attachment self.store.add(self.model.group) self.store.add(self.model) if self.repeat.get_selected() != _ONCE: Payment.create_repeated(self.store, self.model, self.repeat.get_selected(), self.model.due_date.date(), self.end_date.get_date())
def test_get_penalty(self): method = PaymentMethod.get_by_name(self.store, u"check") payment = Payment( value=currency(100), branch=self.create_branch(), due_date=localnow(), method=method, group=None, till=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store, ) for day, expected_value in [(0, 0), (-1, 0), (-30, 0), (30, 0)]: payment.due_date = self._get_relative_day(day) self.assertEqual(payment.get_penalty(), currency(expected_value)) method.penalty = Decimal(20) for day, expected_value in [(0, 0), (-1, 20), (-30, 20), (30, 0)]: payment.due_date = self._get_relative_day(day) self.assertEqual(payment.get_penalty(), currency(expected_value)) due_date = self._get_relative_day(-15) paid_date = self._get_relative_day(-5) payment.due_date = payment.open_date = due_date self.assertEqual(payment.get_penalty(paid_date.date()), currency(20)) self.assertEqual(payment.get_penalty(due_date.date()), currency(0)) for day in (18, -18): paid_date = self._get_relative_day(day) self.assertRaises(ValueError, payment.get_penalty, paid_date.date())
def test_get_days_late(self): method = PaymentMethod.get_by_name(self.store, u'check') open_date = due_date = self._get_relative_day(-4) payment = Payment(value=currency(100), branch=self.create_branch(), due_date=due_date, open_date=open_date, method=method, group=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store) payment.set_pending() self.assertEqual(payment.get_days_late(), 4) payment.due_date = self._get_relative_day(+4) self.assertFalse(payment.get_days_late()) payment.pay() self.assertEqual(payment.get_days_late(), 0)
def test_create_repeated_with_temporary_identifier(self): payment = self.create_payment() payment.description = u'temporary' payments = Payment.create_repeated(self.store, payment, INTERVALTYPE_MONTH, localdate(2012, 1, 1).date(), localdate(2012, 3, 1).date(), temporary_identifiers=True) (self.assertTrue(p.identifier < 0) for p in payments)
def _dialog_payment_details(self, id): from stoqlib.domain.payment.payment import Payment store = api.new_store() payment = Payment.get(int(id), store) dialog_class = get_dialog_for_payment(payment) retval = run_dialog(dialog_class, self.app, store, payment) if store.confirm(retval): self.refresh() store.close()
def test_is_paid(self): method = PaymentMethod.get_by_name(self.store, u'check') payment = Payment(value=currency(100), branch=self.create_branch(), due_date=localnow(), method=method, group=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store) self.failIf(payment.is_paid()) payment.set_pending() self.failIf(payment.is_paid()) payment.pay() self.failUnless(payment.is_paid())
def _create_return_payment(self): money = PaymentMethod.get_by_name(self.store, u'money') description = _(u'Money returned for order %s') % ( self.purchase.identifier, ) value = currency(self.model.paid_value - self.model.received_value) today = localtoday().date() payment = Payment(open_date=today, branch=self.purchase.branch, description=description, value=value, base_value=value, due_date=today, method=money, group=self.purchase.group, category=None, store=self.store, payment_type=Payment.TYPE_IN) payment.set_pending() return payment
def on_confirm(self): self.model.base_value = self.model.value person = self.person.get_selected_data() if (person is not None and person is not ValueUnset and # FIXME: PersonField should never let get_selected_data() # return anything different from None and the model. person != ""): setattr(self.model.group, self.person_attribute, self.store.fetch(person.person)) self.model.attachment = self.fields['attachment'].attachment self.store.add(self.model.group) self.store.add(self.model) if self.repeat.get_selected() != _ONCE: Payment.create_repeated(self.store, self.model, self.repeat.get_selected(), self.model.due_date.date(), self.end_date.get_date())
def test_new(self): payment = Payment(value=currency(10), due_date=localnow(), branch=self.create_branch(), method=None, group=None, till=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store) self.failUnless(payment.status == Payment.STATUS_PREVIEW)
def _create_payments(self, station): nfe_payments = list(self.payments) # FIXME: receive from frontend method = PaymentMethod.get_by_name(store=self.store, name=u"bill") # FIXME: Select method in frontend and add option to split the payment # in more than one duplicate identifier = Payment.get_temporary_identifier(self.store) if not nfe_payments: payment = method.create_payment( branch=self.purchase_order.branch, station=station, payment_type=Payment.TYPE_OUT, payment_group=self.purchase_order.group, value=self.purchase_order.purchase_total, identifier=identifier) payment.status = u'paid' return payment payments = [] for i, item in enumerate(nfe_payments, start=1): identifier = Payment.get_temporary_identifier(self.store) payment = Payment(store=self.store, branch=self.purchase_order.branch, identifier=identifier, value=item.value, base_value=item.value, due_date=item.due_date, status=Payment.STATUS_PAID, group=self.purchase_order.group, method=method, bill_received=True, payment_type=Payment.TYPE_OUT, station=station) payment.description = method.describe_payment( payment.group, i, len(list(nfe_payments))) item.description = payment.description self.purchase_order.group.add_item(payment) payments.append(payment) return payments
def test_create_repeated_month(self): p = self.create_payment() p.description = u"Rent" p.category = self.create_payment_category() with self.assertRaises(AssertionError): Payment.create_repeated( self.store, p, INTERVALTYPE_MONTH, localdate(2012, 1, 1).date(), localdate(2012, 1, 1).date() ) payments = Payment.create_repeated( self.store, p, INTERVALTYPE_MONTH, localdate(2012, 1, 1).date(), localdate(2012, 12, 31).date() ) self.assertEquals(len(payments), 11) self.assertEquals(p.due_date, localdatetime(2012, 1, 1)) self.assertEquals(p.description, u"1/12 Rent") self.assertEquals(payments[0].due_date, localdatetime(2012, 2, 1)) self.assertEquals(payments[1].due_date, localdatetime(2012, 3, 1)) self.assertEquals(payments[10].due_date, localdatetime(2012, 12, 1)) self.assertEquals(payments[0].description, u"2/12 Rent") self.assertEquals(payments[10].description, u"12/12 Rent")
def test_create_repeated_month(self): p = self.create_payment() p.description = u'Rent' p.category = self.create_payment_category() with self.assertRaises(AssertionError): Payment.create_repeated(self.store, p, INTERVALTYPE_MONTH, localdate(2012, 1, 1).date(), localdate(2012, 1, 1).date()) payments = Payment.create_repeated(self.store, p, INTERVALTYPE_MONTH, localdate(2012, 1, 1).date(), localdate(2012, 12, 31).date()) self.assertEqual(len(payments), 11) self.assertEqual(p.due_date, localdatetime(2012, 1, 1)) self.assertEqual(p.description, u'1/12 Rent') self.assertEqual(payments[0].due_date, localdatetime(2012, 2, 1)) self.assertEqual(payments[1].due_date, localdatetime(2012, 3, 1)) self.assertEqual(payments[10].due_date, localdatetime(2012, 12, 1)) self.assertEqual(payments[0].description, u'2/12 Rent') self.assertEqual(payments[10].description, u'12/12 Rent')
def test_cancel(self): method = PaymentMethod.get_by_name(self.store, u'check') payment = Payment(value=currency(100), branch=self.create_branch(), due_date=localnow(), method=method, group=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store) payment.set_pending() payment.pay() payment.cancel(change_entry=payment) self.assertEqual(payment.status, Payment.STATUS_CANCELLED)
def test_get_paid_date_string(self): method = PaymentMethod.get_by_name(self.store, u'check') payment = Payment(value=currency(100), branch=self.create_branch(), due_date=localnow(), method=method, group=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store) today = localnow().strftime(u'%x') self.assertFalse(payment.get_paid_date_string() == today) payment.set_pending() payment.pay() self.assertTrue(payment.get_paid_date_string() == today)
def testCreateRepeatedMonth(self): p = self.create_payment() p.description = u"Rent" p.category = self.create_payment_category() payments = Payment.create_repeated( self.store, p, INTERVALTYPE_MONTH, datetime.date(2012, 1, 1), datetime.date(2012, 12, 31) ) self.assertEquals(len(payments), 11) self.assertEquals(p.due_date, datetime.datetime(2012, 1, 1)) self.assertEquals(p.description, u"1/12 Rent") self.assertEquals(payments[0].due_date, datetime.datetime(2012, 2, 1)) self.assertEquals(payments[1].due_date, datetime.datetime(2012, 3, 1)) self.assertEquals(payments[10].due_date, datetime.datetime(2012, 12, 1)) self.assertEquals(payments[0].description, u"2/12 Rent") self.assertEquals(payments[10].description, u"12/12 Rent")
def test_create_repeated_month(self): p = self.create_payment() p.description = u'Rent' p.category = self.create_payment_category() payments = Payment.create_repeated(self.store, p, INTERVALTYPE_MONTH, localdate(2012, 1, 1).date(), localdate(2012, 12, 31).date()) self.assertEquals(len(payments), 11) self.assertEquals(p.due_date, localdatetime(2012, 1, 1)) self.assertEquals(p.description, u'1/12 Rent') self.assertEquals(payments[0].due_date, localdatetime(2012, 2, 1)) self.assertEquals(payments[1].due_date, localdatetime(2012, 3, 1)) self.assertEquals(payments[10].due_date, localdatetime(2012, 12, 1)) self.assertEquals(payments[0].description, u'2/12 Rent') self.assertEquals(payments[10].description, u'12/12 Rent')
def create_model(self, store): group = PaymentGroup() money = PaymentMethod.get_by_name(store, u'money') branch = api.get_current_branch(store) # Set status to PENDING now, to avoid calling set_pending on # on_confirm for payments that shoud not have its status changed. return Payment(open_date=localtoday().date(), branch=branch, status=Payment.STATUS_PENDING, description=u'', value=currency(0), base_value=currency(0), due_date=None, method=money, group=group, category=None, payment_type=self.payment_type, bill_received=False)
def create_payment(self, payment_type=None, date=None, value=None, method=None, branch=None, group=None): from stoqlib.domain.payment.payment import Payment if payment_type is None: payment_type = Payment.TYPE_OUT if not date: date = localtoday().date() return Payment(group=group or self.create_payment_group(), description=u'Test payment', branch=branch or get_current_branch(self.store), open_date=date, due_date=date, value=Decimal(value or 10), till=None, method=method or self.get_payment_method(), category=None, store=self.store, payment_type=payment_type)
def testCancel(self): method = PaymentMethod.get_by_name(self.store, u"check") payment = Payment( value=currency(100), branch=self.create_branch(), due_date=datetime.datetime.now(), method=method, group=None, till=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store, ) payment.set_pending() payment.pay() payment.cancel() self.assertEqual(payment.status, Payment.STATUS_CANCELLED)
def test_get_paid_date_string(self): method = PaymentMethod.get_by_name(self.store, u"check") payment = Payment( value=currency(100), branch=self.create_branch(), due_date=localnow(), method=method, group=None, till=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store, ) today = localnow().strftime(u"%x") self.failIf(payment.get_paid_date_string() == today) payment.set_pending() payment.pay() self.failUnless(payment.get_paid_date_string() == today)
def testGetInterest(self): method = PaymentMethod.get_by_name(self.store, u'check') payment = Payment(value=currency(100), branch=self.create_branch(), due_date=localnow(), open_date=localnow(), method=method, group=None, till=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store) for day, expected_value in [(0, 0), (-1, 0), (-30, 0), (30, 0)]: payment.due_date = self._get_relative_day(day) self.assertEqual(payment.get_interest(), currency(expected_value)) method.daily_interest = Decimal(1) for day, expected_value in [(0, 0), (-1, 1), (-30, 30), (30, 0)]: payment.due_date = self._get_relative_day(day) self.assertEqual(payment.get_interest(), currency(expected_value)) due_date = self._get_relative_day(-15) paid_date = self._get_relative_day(-5) payment.due_date = payment.open_date = due_date method.daily_interest = Decimal(2) self.assertEqual(payment.get_interest(paid_date.date()), currency(20)) self.assertEqual(payment.get_interest(due_date.date()), currency(0)) for day in (18, -18): paid_date = self._get_relative_day(day) self.assertRaises(ValueError, payment.get_interest, paid_date.date())
def create_payment(self, payment_type, payment_group, branch, value, due_date=None, description=None, base_value=None, till=ValueUnset, payment_number=None): """Creates a new payment according to a payment method interface :param payment_type: the kind of payment, in or out :param payment_group: a :class:`PaymentGroup` subclass :param branch: the :class:`branch <stoqlib.domain.person.Branch>` associated with the payment, for incoming payments this is the branch receiving the payment and for outgoing payments this is the branch sending the payment. :param value: value of payment :param due_date: optional, due date of payment :param details: optional :param description: optional, description of the payment :param base_value: optional :param till: optional :param payment_number: optional :returns: a :class:`payment <stoqlib.domain.payment.Payment>` """ store = self.store if due_date is None: due_date = TransactionTimestamp() if payment_type == Payment.TYPE_IN: query = And(Payment.group_id == payment_group.id, Payment.method_id == self.id, Payment.payment_type == Payment.TYPE_IN, Payment.status != Payment.STATUS_CANCELLED) payment_count = store.find(Payment, query).count() if payment_count == self.max_installments: raise PaymentMethodError( _('You can not create more inpayments for this payment ' 'group since the maximum allowed for this payment ' 'method is %d') % self.max_installments) elif payment_count > self.max_installments: raise DatabaseInconsistency( _('You have more inpayments in database than the maximum ' 'allowed for this payment method')) if not description: description = self.describe_payment(payment_group) # If till is unset, do some clever guessing if till is ValueUnset: # We only need a till for inpayments if payment_type == Payment.TYPE_IN: till = Till.get_current(store) elif payment_type == Payment.TYPE_OUT: till = None else: raise AssertionError(payment_type) payment = Payment(store=store, branch=branch, payment_type=payment_type, due_date=due_date, value=value, base_value=base_value, group=payment_group, method=self, category=None, till=till, description=description, payment_number=payment_number) self.operation.payment_create(payment) return payment
def test_is_cancelled(self): method = PaymentMethod.get_by_name(self.store, u'check') payment = Payment(value=currency(100), branch=self.create_branch(), station=self.current_station, due_date=localnow(), method=method, group=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store) self.assertFalse(payment.is_cancelled()) payment.set_pending() self.assertFalse(payment.is_cancelled()) payment.pay() self.assertFalse(payment.is_cancelled()) payment.cancel() self.assertTrue(payment.is_cancelled()) with self.assertRaises(StoqlibError): payment.status = Payment.STATUS_CANCELLED payment.cancel()
def test_is_cancelled(self): method = PaymentMethod.get_by_name(self.store, u'check') payment = Payment(value=currency(100), branch=self.create_branch(), due_date=localnow(), method=method, group=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store) self.failIf(payment.is_cancelled()) payment.set_pending() self.failIf(payment.is_cancelled()) payment.pay() self.failIf(payment.is_cancelled()) payment.cancel() self.failUnless(payment.is_cancelled()) with self.assertRaises(StoqlibError): payment.status = Payment.STATUS_CANCELLED payment.cancel()
def create_payment(self, branch, station: BranchStation, payment_type, payment_group, value, due_date=None, description=None, base_value=None, payment_number=None, identifier=None, ignore_max_installments=False): """Creates a new payment according to a payment method interface :param payment_type: the kind of payment, in or out :param payment_group: a :class:`PaymentGroup` subclass :param branch: the :class:`branch <stoqlib.domain.person.Branch>` associated with the payment, for incoming payments this is the branch receiving the payment and for outgoing payments this is the branch sending the payment. :param value: value of payment :param due_date: optional, due date of payment :param details: optional :param description: optional, description of the payment :param base_value: optional :param payment_number: optional :param ignore_max_installments: optional, defines whether max_installments should be ignored. :returns: a :class:`payment <stoqlib.domain.payment.Payment>` """ store = self.store if due_date is None: due_date = TransactionTimestamp() if not ignore_max_installments and payment_type == Payment.TYPE_IN: query = And(Payment.group_id == payment_group.id, Payment.method_id == self.id, Payment.payment_type == Payment.TYPE_IN, Payment.status != Payment.STATUS_CANCELLED) payment_count = store.find(Payment, query).count() if payment_count == self.max_installments: raise PaymentMethodError( _('You can not create more inpayments for this payment ' 'group since the maximum allowed for this payment ' 'method is %d') % self.max_installments) elif payment_count > self.max_installments: raise DatabaseInconsistency( _('You have more inpayments in database than the maximum ' 'allowed for this payment method')) if not description: description = self.describe_payment(payment_group) payment = Payment(store=store, branch=branch, station=station, identifier=identifier, payment_type=payment_type, due_date=due_date, value=value, base_value=base_value, group=payment_group, method=self, category=None, description=description, payment_number=payment_number) self.operation.payment_create(payment) return payment
def testIsCancelled(self): method = PaymentMethod.get_by_name(self.store, u"check") payment = Payment( value=currency(100), branch=self.create_branch(), due_date=datetime.datetime.now(), method=method, group=None, till=None, category=None, payment_type=Payment.TYPE_OUT, store=self.store, ) self.failIf(payment.is_cancelled()) payment.set_pending() self.failIf(payment.is_cancelled()) payment.pay() self.failIf(payment.is_cancelled()) payment.cancel() self.failUnless(payment.is_cancelled())