invoicing: add user_name on lines (#73514)
This commit is contained in:
parent
f49b9b8d03
commit
9f85afd377
|
@ -0,0 +1,23 @@
|
|||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('invoicing', '0008_injected_line'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='draftinvoiceline',
|
||||
name='user_name',
|
||||
field=models.CharField(default='', max_length=250),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='invoiceline',
|
||||
name='user_name',
|
||||
field=models.CharField(default='', max_length=250),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -152,11 +152,9 @@ class Pool(models.Model):
|
|||
# get agendas with pricing corresponding to the period
|
||||
agendas = utils.get_agendas(pool=self)
|
||||
# get subscribed users for each agenda, for the period
|
||||
user_external_ids = utils.get_users_from_subscriptions(agendas=agendas, pool=self)
|
||||
users = utils.get_users_from_subscriptions(agendas=agendas, pool=self)
|
||||
# get invoice lines for all subscribed users, for each agenda in the corresponding period
|
||||
lines = utils.get_all_invoice_lines(
|
||||
agendas=agendas, user_external_ids=user_external_ids, pool=self
|
||||
)
|
||||
lines = utils.get_all_invoice_lines(agendas=agendas, users=users, pool=self)
|
||||
# and generate invoices
|
||||
utils.generate_invoices_from_lines(agendas=agendas, all_lines=lines, pool=self)
|
||||
except (RegieNotConfigured, ChronoError) as e:
|
||||
|
@ -215,6 +213,7 @@ class AbstractInvoiceLine(models.Model):
|
|||
total_amount = models.DecimalField(max_digits=9, decimal_places=2)
|
||||
|
||||
user_external_id = models.CharField(max_length=250)
|
||||
user_name = models.CharField(max_length=250)
|
||||
payer_external_id = models.CharField(max_length=250)
|
||||
event = JSONField(default=dict)
|
||||
pricing_data = JSONField(default=dict, encoder=DjangoJSONEncoder)
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
<td>{{ line.quantity }}</td>
|
||||
<td>{{ line.unit_amount }}</td>
|
||||
<td>{{ line.total_amount }}</td>
|
||||
<td>{{ line.user_external_id }}</td>
|
||||
<td>{{ line.user_name }} ({{ line.user_external_id }})</td>
|
||||
<td>{{ line.payer_external_id }}</td>
|
||||
<td class="status">
|
||||
<span class="tag tag-{{ line.status }}">{{ line.get_status_display }}</span>
|
||||
|
|
|
@ -35,7 +35,7 @@ def get_agendas(pool):
|
|||
|
||||
|
||||
def get_users_from_subscriptions(agendas, pool):
|
||||
user_external_ids = set()
|
||||
users = {}
|
||||
for agenda in agendas:
|
||||
subscriptions = get_subscriptions(
|
||||
agenda_slug=agenda.slug,
|
||||
|
@ -43,11 +43,15 @@ def get_users_from_subscriptions(agendas, pool):
|
|||
date_end=pool.campaign.date_end,
|
||||
)
|
||||
for subscription in subscriptions:
|
||||
user_external_ids.add(subscription['user_external_id'])
|
||||
return user_external_ids
|
||||
user_external_id = subscription['user_external_id']
|
||||
if user_external_id in users:
|
||||
continue
|
||||
user_name = '%s %s' % (subscription['user_first_name'], subscription['user_last_name'])
|
||||
users[user_external_id] = user_name.strip()[:250] or user_external_id
|
||||
return [(user_id, user_name) for user_id, user_name in users.items()]
|
||||
|
||||
|
||||
def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, pool):
|
||||
def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, user_name, pool):
|
||||
def get_agenda_pricing(agendas_pricings_for_agenda, date_event):
|
||||
# same logic as AgendaPricing.get_agenda_pricing
|
||||
for agenda_pricing in agendas_pricings_for_agenda:
|
||||
|
@ -110,6 +114,7 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, pool
|
|||
unit_amount=0,
|
||||
total_amount=0,
|
||||
user_external_id=user_external_id,
|
||||
user_name=user_name,
|
||||
payer_external_id=user_external_id, # XXX
|
||||
event=serialized_event,
|
||||
pricing_data=pricing_error,
|
||||
|
@ -127,6 +132,7 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, pool
|
|||
unit_amount=pricing_data['pricing'],
|
||||
total_amount=pricing_data['pricing'],
|
||||
user_external_id=user_external_id,
|
||||
user_name=user_name,
|
||||
payer_external_id=user_external_id, # XXX
|
||||
event=serialized_event,
|
||||
pricing_data=pricing_data,
|
||||
|
@ -162,7 +168,8 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, pool
|
|||
quantity=injected_line.quantity,
|
||||
unit_amount=injected_line.unit_amount,
|
||||
total_amount=injected_line.total_amount,
|
||||
user_external_id=injected_line.user_external_id,
|
||||
user_external_id=user_external_id,
|
||||
user_name=user_name,
|
||||
payer_external_id=injected_line.user_external_id,
|
||||
status='success',
|
||||
pool=pool,
|
||||
|
@ -175,7 +182,7 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, pool
|
|||
return lines
|
||||
|
||||
|
||||
def get_all_invoice_lines(agendas, user_external_ids, pool):
|
||||
def get_all_invoice_lines(agendas, users, pool):
|
||||
agendas_pricings = (
|
||||
AgendaPricing.objects.filter(flat_fee_schedule=False)
|
||||
.extra(
|
||||
|
@ -186,12 +193,13 @@ def get_all_invoice_lines(agendas, user_external_ids, pool):
|
|||
)
|
||||
|
||||
lines = []
|
||||
for user_external_id in user_external_ids:
|
||||
for user_external_id, user_name in users:
|
||||
# generate lines for each user
|
||||
lines += get_invoice_lines_for_user(
|
||||
agendas=agendas,
|
||||
agendas_pricings=agendas_pricings,
|
||||
user_external_id=user_external_id,
|
||||
user_name=user_name,
|
||||
pool=pool,
|
||||
)
|
||||
return lines
|
||||
|
|
|
@ -130,12 +130,12 @@ def test_get_users_from_subscriptions(mock_subscriptions):
|
|||
)
|
||||
|
||||
# no agendas
|
||||
assert utils.get_users_from_subscriptions(agendas=[], pool=pool) == set()
|
||||
assert utils.get_users_from_subscriptions(agendas=[], pool=pool) == []
|
||||
assert mock_subscriptions.call_args_list == []
|
||||
|
||||
# no subscriptions
|
||||
mock_subscriptions.return_value = []
|
||||
assert utils.get_users_from_subscriptions(agendas=[agenda1, agenda2], pool=pool) == set()
|
||||
assert utils.get_users_from_subscriptions(agendas=[agenda1, agenda2], pool=pool) == []
|
||||
assert mock_subscriptions.call_args_list == [
|
||||
mock.call(
|
||||
agenda_slug='agenda-1', date_start=datetime.date(2022, 9, 1), date_end=datetime.date(2022, 10, 1)
|
||||
|
@ -151,16 +151,22 @@ def test_get_users_from_subscriptions(mock_subscriptions):
|
|||
[
|
||||
{
|
||||
'user_external_id': 'user:1',
|
||||
'user_first_name': 'User1',
|
||||
'user_last_name': 'Name1',
|
||||
'date_start': '2022-08-01',
|
||||
'date_end': '2022-09-02',
|
||||
},
|
||||
{
|
||||
'user_external_id': 'user:1',
|
||||
'user_first_name': 'Foo Bar',
|
||||
'user_last_name': '',
|
||||
'date_start': '2022-09-02',
|
||||
'date_end': '2022-09-03',
|
||||
},
|
||||
{
|
||||
'user_external_id': 'user:2',
|
||||
'user_first_name': '',
|
||||
'user_last_name': '',
|
||||
'date_start': '2022-09-02',
|
||||
'date_end': '2022-09-03',
|
||||
},
|
||||
|
@ -168,12 +174,17 @@ def test_get_users_from_subscriptions(mock_subscriptions):
|
|||
[
|
||||
{
|
||||
'user_external_id': 'user:1',
|
||||
'user_first_name': 'User1 Name1',
|
||||
'user_last_name': '',
|
||||
'date_start': '2022-08-01',
|
||||
'date_end': '2022-10-01',
|
||||
},
|
||||
],
|
||||
]
|
||||
assert utils.get_users_from_subscriptions(agendas=[agenda1, agenda2], pool=pool) == {'user:1', 'user:2'}
|
||||
assert utils.get_users_from_subscriptions(agendas=[agenda1, agenda2], pool=pool) == [
|
||||
('user:1', 'User1 Name1'),
|
||||
('user:2', 'user:2'),
|
||||
]
|
||||
assert mock_subscriptions.call_args_list == [
|
||||
mock.call(
|
||||
agenda_slug='agenda-1', date_start=datetime.date(2022, 9, 1), date_end=datetime.date(2022, 10, 1)
|
||||
|
@ -202,6 +213,7 @@ def test_get_invoice_lines_for_user_check_status_error(mock_status):
|
|||
agendas=[agenda],
|
||||
agendas_pricings=[],
|
||||
user_external_id='user:1',
|
||||
user_name='User1 Name1',
|
||||
pool=pool,
|
||||
)
|
||||
|
||||
|
@ -351,6 +363,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
|
|||
agendas=[],
|
||||
agendas_pricings=[agenda_pricing],
|
||||
user_external_id='user:1',
|
||||
user_name='User1 Name1',
|
||||
pool=pool,
|
||||
)
|
||||
== []
|
||||
|
@ -364,6 +377,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
|
|||
agendas=[agenda1, agenda2],
|
||||
agendas_pricings=[agenda_pricing],
|
||||
user_external_id='user:1',
|
||||
user_name='User1 Name1',
|
||||
pool=pool,
|
||||
)
|
||||
assert len(lines) == 2 # injected lines
|
||||
|
@ -433,6 +447,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
|
|||
agendas=[agenda1, agenda2],
|
||||
agendas_pricings=[agenda_pricing],
|
||||
user_external_id='user:1',
|
||||
user_name='User1 Name1',
|
||||
pool=pool,
|
||||
)
|
||||
assert mock_pricing_data_event.call_args_list == [
|
||||
|
@ -499,6 +514,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
|
|||
assert line1.unit_amount == 1
|
||||
assert line1.total_amount == 1
|
||||
assert line1.user_external_id == 'user:1'
|
||||
assert line1.user_name == 'User1 Name1'
|
||||
assert line1.payer_external_id == 'user:1'
|
||||
assert line1.event == {
|
||||
'agenda': 'agenda-1',
|
||||
|
@ -518,6 +534,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
|
|||
assert line2.unit_amount == 2
|
||||
assert line2.total_amount == 2
|
||||
assert line2.user_external_id == 'user:1'
|
||||
assert line2.user_name == 'User1 Name1'
|
||||
assert line2.payer_external_id == 'user:1'
|
||||
assert line2.event == {
|
||||
'agenda': 'agenda-1',
|
||||
|
@ -537,6 +554,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
|
|||
assert line3.unit_amount == 3
|
||||
assert line3.total_amount == 3
|
||||
assert line3.user_external_id == 'user:1'
|
||||
assert line3.user_name == 'User1 Name1'
|
||||
assert line3.payer_external_id == 'user:1'
|
||||
assert line3.event == {
|
||||
'agenda': 'agenda-2',
|
||||
|
@ -556,6 +574,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
|
|||
assert line4.unit_amount == 4
|
||||
assert line4.total_amount == 4
|
||||
assert line4.user_external_id == 'user:1'
|
||||
assert line4.user_name == 'User1 Name1'
|
||||
assert line4.payer_external_id == 'user:1'
|
||||
assert line4.event == {
|
||||
'agenda': 'agenda-2',
|
||||
|
@ -575,6 +594,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
|
|||
assert line5.unit_amount == 1.5
|
||||
assert line5.total_amount == 3
|
||||
assert line5.user_external_id == 'user:1'
|
||||
assert line5.user_name == 'User1 Name1'
|
||||
assert line5.payer_external_id == 'user:1'
|
||||
assert line5.event == {}
|
||||
assert line5.pricing_data == {}
|
||||
|
@ -589,6 +609,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
|
|||
assert line6.unit_amount == 1.5
|
||||
assert line6.total_amount == 4.5
|
||||
assert line6.user_external_id == 'user:1'
|
||||
assert line6.user_name == 'User1 Name1'
|
||||
assert line6.payer_external_id == 'user:1'
|
||||
assert line6.event == {}
|
||||
assert line6.pricing_data == {}
|
||||
|
@ -652,6 +673,7 @@ def test_get_invoice_lines_for_user_check_status_agenda_pricing_dates(mock_statu
|
|||
agendas=[agenda],
|
||||
agendas_pricings=AgendaPricing.objects.all(),
|
||||
user_external_id='user:1',
|
||||
user_name='User1 Name1',
|
||||
pool=pool,
|
||||
)
|
||||
assert len(lines) == 1
|
||||
|
@ -677,6 +699,7 @@ def test_get_invoice_lines_for_user_check_status_agenda_pricing_dates(mock_statu
|
|||
agendas=[agenda],
|
||||
agendas_pricings=AgendaPricing.objects.all(),
|
||||
user_external_id='user:1',
|
||||
user_name='User1 Name1',
|
||||
pool=pool,
|
||||
)
|
||||
assert len(lines) == 1
|
||||
|
@ -701,6 +724,7 @@ def test_get_invoice_lines_for_user_check_status_agenda_pricing_dates(mock_statu
|
|||
agendas=[agenda],
|
||||
agendas_pricings=AgendaPricing.objects.all(),
|
||||
user_external_id='user:1',
|
||||
user_name='User1 Name1',
|
||||
pool=pool,
|
||||
)
|
||||
assert len(lines) == 1
|
||||
|
@ -713,6 +737,7 @@ def test_get_invoice_lines_for_user_check_status_agenda_pricing_dates(mock_statu
|
|||
assert line.unit_amount == 0
|
||||
assert line.total_amount == 0
|
||||
assert line.user_external_id == 'user:1'
|
||||
assert line.user_name == 'User1 Name1'
|
||||
assert line.payer_external_id == 'user:1'
|
||||
assert line.event == {
|
||||
'agenda': 'agenda',
|
||||
|
@ -788,6 +813,7 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data
|
|||
agendas=[agenda],
|
||||
agendas_pricings=[agenda_pricing],
|
||||
user_external_id='user:1',
|
||||
user_name='User1 Name1',
|
||||
pool=pool,
|
||||
)
|
||||
assert len(lines) == 3
|
||||
|
@ -800,6 +826,7 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data
|
|||
assert line1.unit_amount == 1
|
||||
assert line1.total_amount == 1
|
||||
assert line1.user_external_id == 'user:1'
|
||||
assert line1.user_name == 'User1 Name1'
|
||||
assert line1.payer_external_id == 'user:1'
|
||||
assert line1.event == {
|
||||
'agenda': 'agenda',
|
||||
|
@ -818,6 +845,7 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data
|
|||
assert line2.unit_amount == 0
|
||||
assert line2.total_amount == 0
|
||||
assert line2.user_external_id == 'user:1'
|
||||
assert line2.user_name == 'User1 Name1'
|
||||
assert line2.payer_external_id == 'user:1'
|
||||
assert line2.event == {
|
||||
'agenda': 'agenda',
|
||||
|
@ -836,6 +864,7 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data
|
|||
assert line3.unit_amount == 3
|
||||
assert line3.total_amount == 3
|
||||
assert line3.user_external_id == 'user:1'
|
||||
assert line3.user_name == 'User1 Name1'
|
||||
assert line3.payer_external_id == 'user:1'
|
||||
assert line3.event == {
|
||||
'agenda': 'agenda',
|
||||
|
@ -888,7 +917,7 @@ def test_get_all_invoice_lines(mock_user_lines):
|
|||
assert (
|
||||
utils.get_all_invoice_lines(
|
||||
agendas=[agenda1, agenda2],
|
||||
user_external_ids=[],
|
||||
users=[],
|
||||
pool=pool,
|
||||
)
|
||||
== []
|
||||
|
@ -898,7 +927,7 @@ def test_get_all_invoice_lines(mock_user_lines):
|
|||
# with subscribed users
|
||||
assert utils.get_all_invoice_lines(
|
||||
agendas=[agenda1, agenda2],
|
||||
user_external_ids=['user:1', 'user:2'],
|
||||
users=[('user:1', 'User1 Name1'), ('user:2', 'User2 Name2')],
|
||||
pool=pool,
|
||||
) == [line1, line2, line3]
|
||||
assert mock_user_lines.call_args_list == [
|
||||
|
@ -906,12 +935,14 @@ def test_get_all_invoice_lines(mock_user_lines):
|
|||
agendas=[agenda1, agenda2],
|
||||
agendas_pricings=mock.ANY,
|
||||
user_external_id='user:1',
|
||||
user_name='User1 Name1',
|
||||
pool=pool,
|
||||
),
|
||||
mock.call(
|
||||
agendas=[agenda1, agenda2],
|
||||
agendas_pricings=mock.ANY,
|
||||
user_external_id='user:2',
|
||||
user_name='User2 Name2',
|
||||
pool=pool,
|
||||
),
|
||||
]
|
||||
|
@ -1018,7 +1049,7 @@ def test_get_all_invoice_lines_queryset(mock_status):
|
|||
with CaptureQueriesContext(connection) as ctx:
|
||||
lines = utils.get_all_invoice_lines(
|
||||
agendas=[agenda1, agenda2],
|
||||
user_external_ids=['user:1', 'user:2'],
|
||||
users=[('user:1', 'User1 Name1'), ('user:2', 'User2 Name2')],
|
||||
pool=pool,
|
||||
)
|
||||
assert lines
|
||||
|
@ -1232,7 +1263,7 @@ def test_generate_invoices(mock_generate, mock_lines, mock_users, mock_agendas):
|
|||
assert mock_lines.call_args_list == [
|
||||
mock.call(
|
||||
agendas=[agenda1, agenda2],
|
||||
user_external_ids=['foo', 'bar'],
|
||||
users=['foo', 'bar'],
|
||||
pool=pool,
|
||||
)
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue