Refs #654 -- Allow to update invoice addresses

This commit is contained in:
Raphael Michel
2019-03-23 13:51:25 +01:00
parent 420649e10a
commit 991e4127f6
4 changed files with 102 additions and 6 deletions

View File

@@ -578,6 +578,8 @@ Updating order fields
* ``comment`` * ``comment``
* ``invoice_address`` (you always need to supply the full object, or ``null`` to delete the current address)
**Example request**: **Example request**:
.. sourcecode:: http .. sourcecode:: http

View File

@@ -220,7 +220,7 @@ class OrderRefundSerializer(I18nAwareModelSerializer):
class OrderSerializer(I18nAwareModelSerializer): class OrderSerializer(I18nAwareModelSerializer):
invoice_address = InvoiceAddressSerializer(read_only=True) invoice_address = InvoiceAddressSerializer(allow_null=True)
positions = OrderPositionSerializer(many=True, read_only=True) positions = OrderPositionSerializer(many=True, read_only=True)
fees = OrderFeeSerializer(many=True, read_only=True) fees = OrderFeeSerializer(many=True, read_only=True)
downloads = OrderDownloadsField(source='*', read_only=True) downloads = OrderDownloadsField(source='*', read_only=True)
@@ -238,7 +238,7 @@ class OrderSerializer(I18nAwareModelSerializer):
) )
read_only_fields = ( read_only_fields = (
'code', 'status', 'testmode', 'secret', 'datetime', 'expires', 'payment_date', 'code', 'status', 'testmode', 'secret', 'datetime', 'expires', 'payment_date',
'payment_provider', 'fees', 'total', 'invoice_address', 'positions', 'downloads', 'payment_provider', 'fees', 'total', 'positions', 'downloads',
'last_modified', 'payments', 'refunds', 'require_approval', 'sales_channel' 'last_modified', 'payments', 'refunds', 'require_approval', 'sales_channel'
) )
@@ -256,10 +256,34 @@ class OrderSerializer(I18nAwareModelSerializer):
# Even though all fields that shouldn't be edited are marked as read_only in the serializer # Even though all fields that shouldn't be edited are marked as read_only in the serializer
# (hopefully), we'll be extra careful here and be explicit about the model fields we update. # (hopefully), we'll be extra careful here and be explicit about the model fields we update.
update_fields = ['comment', 'checkin_attention', 'email', 'locale'] update_fields = ['comment', 'checkin_attention', 'email', 'locale']
print(validated_data)
if 'invoice_address' in validated_data:
iadata = validated_data.pop('invoice_address')
if not iadata:
try:
instance.invoice_address.delete()
except InvoiceAddress.DoesNotExist:
pass
else:
name = iadata.pop('name', '')
if name and not iadata.get('name_parts'):
iadata['name_parts'] = {
'_legacy': name
}
try:
ia = instance.invoice_address
if iadata.get('vat_id') != ia.vat_id:
ia.vat_id_validated = False
self.fields['invoice_address'].update(ia, iadata)
except InvoiceAddress.DoesNotExist:
InvoiceAddress.objects.create(order=instance, **iadata)
for attr, value in validated_data.items(): for attr, value in validated_data.items():
if attr in update_fields: if attr in update_fields:
setattr(instance, attr, value) setattr(instance, attr, value)
instance.save(update_fields=update_fields) instance.save(update_fields=update_fields)
return instance return instance

View File

@@ -494,6 +494,16 @@ class OrderViewSet(viewsets.ModelViewSet):
} }
) )
if 'invoice_address' in self.request.data:
serializer.instance.log_action(
'pretix.event.order.modified',
user=self.request.user,
auth=self.request.auth,
data={
'invoice_data': self.request.data.get('invoice_address'),
}
)
serializer.save() serializer.save()
def perform_create(self, serializer): def perform_create(self, serializer):

View File

@@ -94,7 +94,8 @@ def order(event, item, taxrule, question):
) )
o.fees.create(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.25'), tax_rate=Decimal('19.00'), o.fees.create(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.25'), tax_rate=Decimal('19.00'),
tax_value=Decimal('0.05'), tax_rule=taxrule) tax_value=Decimal('0.05'), tax_rule=taxrule)
InvoiceAddress.objects.create(order=o, company="Sample company", country=Country('NZ')) InvoiceAddress.objects.create(order=o, company="Sample company", country=Country('NZ'),
vat_id="DE123", vat_id_validated=True)
op = OrderPosition.objects.create( op = OrderPosition.objects.create(
order=o, order=o,
item=item, item=item,
@@ -214,8 +215,8 @@ TEST_ORDER_RES = {
"city": "", "city": "",
"country": "NZ", "country": "NZ",
"internal_reference": "", "internal_reference": "",
"vat_id": "", "vat_id": "DE123",
"vat_id_validated": False "vat_id_validated": True
}, },
"require_approval": False, "require_approval": False,
"positions": [TEST_ORDERPOSITION_RES], "positions": [TEST_ORDERPOSITION_RES],
@@ -2586,7 +2587,19 @@ def test_order_update_allowed_fields(token_client, organizer, event, order):
'comment': 'Here is a comment', 'comment': 'Here is a comment',
'checkin_attention': True, 'checkin_attention': True,
'email': 'foo@bar.com', 'email': 'foo@bar.com',
'locale': 'de' 'locale': 'de',
'invoice_address': {
"is_business": False,
"company": "This is my company name",
"name": "John Doe",
"name_parts": {},
"street": "",
"zipcode": "",
"city": "Paris",
"country": "Fr",
"internal_reference": "",
"vat_id": "",
}
} }
) )
assert resp.status_code == 200 assert resp.status_code == 200
@@ -2595,10 +2608,57 @@ def test_order_update_allowed_fields(token_client, organizer, event, order):
assert order.checkin_attention assert order.checkin_attention
assert order.email == 'foo@bar.com' assert order.email == 'foo@bar.com'
assert order.locale == 'de' assert order.locale == 'de'
assert order.invoice_address.company == "This is my company name"
assert order.invoice_address.name_cached == "John Doe"
assert order.invoice_address.name_parts == {'_legacy': 'John Doe'}
assert str(order.invoice_address.country) == "FR"
assert not order.invoice_address.vat_id_validated
assert order.invoice_address.city == "Paris"
assert order.all_logentries().get(action_type='pretix.event.order.comment') assert order.all_logentries().get(action_type='pretix.event.order.comment')
assert order.all_logentries().get(action_type='pretix.event.order.checkin_attention') assert order.all_logentries().get(action_type='pretix.event.order.checkin_attention')
assert order.all_logentries().get(action_type='pretix.event.order.contact.changed') assert order.all_logentries().get(action_type='pretix.event.order.contact.changed')
assert order.all_logentries().get(action_type='pretix.event.order.locale.changed') assert order.all_logentries().get(action_type='pretix.event.order.locale.changed')
assert order.all_logentries().get(action_type='pretix.event.order.modified')
@pytest.mark.django_db
def test_order_update_invoiceaddress_delete_create(token_client, organizer, event, order):
event.settings.locales = ['de', 'en']
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/orders/{}/'.format(
organizer.slug, event.slug, order.code
), format='json', data={
'invoice_address': None,
}
)
assert resp.status_code == 200
order.refresh_from_db()
with pytest.raises(InvoiceAddress.DoesNotExist):
order.invoice_address
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/orders/{}/'.format(
organizer.slug, event.slug, order.code
), format='json', data={
'invoice_address': {
"is_business": False,
"company": "This is my company name",
"name": "",
"name_parts": {},
"street": "",
"zipcode": "",
"city": "Paris",
"country": "Fr",
"internal_reference": "",
"vat_id": "",
}
}
)
assert resp.status_code == 200
order.refresh_from_db()
assert order.invoice_address.company == "This is my company name"
assert str(order.invoice_address.country) == "FR"
assert order.invoice_address.city == "Paris"
@pytest.mark.django_db @pytest.mark.django_db