Projet

Général

Profil

0005-pricing-flat-fee-schedule-overlapping-67675.patch

Lauréline Guérin, 29 juillet 2022 21:57

Télécharger (12,3 ko)

Voir les différences:

Subject: [PATCH 05/14] pricing: flat fee schedule & overlapping (#67675)

 lingo/pricing/forms.py                        |  39 ++++-
 .../lingo/pricing/manager_agenda_detail.html  |  18 +++
 lingo/pricing/views.py                        |   7 +-
 tests/pricing/manager/test_agenda_pricing.py  | 151 +++++++++++++++++-
 4 files changed, 212 insertions(+), 3 deletions(-)
lingo/pricing/forms.py
184 184
                )
185 185
        return subscription_required
186 186

  
187
    def clean(self):
188
        cleaned_data = super().clean()
189
        if (
190
            'date_start' in cleaned_data
191
            and 'date_end' in cleaned_data
192
            and 'flat_fee_schedule' in cleaned_data
193
        ):
194
            old_date_start = self.instance.date_start
195
            old_date_end = self.instance.date_end
196
            old_flat_fee_schedule = self.instance.flat_fee_schedule
197
            new_date_start = cleaned_data['date_start']
198
            new_date_end = cleaned_data['date_end']
199
            new_flat_fee_schedule = cleaned_data['flat_fee_schedule']
200
            if (
201
                old_date_start != new_date_start
202
                or old_date_end != new_date_end
203
                or old_flat_fee_schedule != new_flat_fee_schedule
204
            ):
205
                overlapping_qs = (
206
                    AgendaPricing.objects.filter(flat_fee_schedule=new_flat_fee_schedule)
207
                    .exclude(pk=self.instance.pk)
208
                    .extra(
209
                        where=["(date_start, date_end) OVERLAPS (%s, %s)"],
210
                        params=[new_date_start, new_date_end],
211
                    )
212
                )
213
                for agenda in self.instance.agendas.all():
214
                    if overlapping_qs.filter(agendas=agenda).exists():
215
                        self.add_error(
216
                            None,
217
                            _('Agenda "%s" has already a pricing overlapping this period.') % agenda.label,
218
                        )
219

  
220
        return cleaned_data
221

  
187 222

  
188 223
class AgendaPricingAgendaAddForm(forms.Form):
189 224
    agenda = forms.ModelChoiceField(label=_('Agenda to add'), queryset=Agenda.objects.none(), required=True)
......
195 230

  
196 231
    def clean_agenda(self):
197 232
        agenda = self.cleaned_data['agenda']
198
        overlapping_qs = AgendaPricing.objects.filter(agendas=agenda).extra(
233
        overlapping_qs = AgendaPricing.objects.filter(
234
            flat_fee_schedule=self.agenda_pricing.flat_fee_schedule, agendas=agenda
235
        ).extra(
199 236
            where=["(date_start, date_end) OVERLAPS (%s, %s)"],
200 237
            params=[self.agenda_pricing.date_start, self.agenda_pricing.date_end],
201 238
        )
lingo/pricing/templates/lingo/pricing/manager_agenda_detail.html
26 26
  <div class="pk-tabs--container">
27 27

  
28 28
    <div aria-labelledby="tab-pricings" id="panel-pricings" role="tabpanel" tabindex="0">
29
      <h3>{% trans "Pricings" context 'agenda pricing' %}</h3>
29 30
      {% if agenda_pricings %}
30 31
      <ul class="objects-list single-links">
31 32
      {% for agenda_pricing in agenda_pricings %}
......
42 43
        {% endblocktrans %}
43 44
      </div>
44 45
      {% endif %}
46
      <h3>{% trans "Flat fee schedule pricings" %}</h3>
47
      {% if agenda_pricings_flat %}
48
      <ul class="objects-list single-links">
49
      {% for agenda_pricing in agenda_pricings_flat %}
50
        <li>
51
          <a href="{% url 'lingo-manager-agenda-pricing-detail' agenda_pricing.pk %}">{{ agenda_pricing.pricing }} ({{ agenda_pricing.date_start|date:'d/m/Y' }} - {{ agenda_pricing.date_end|date:'d/m/Y' }})</a>
52
          <a href="{% url 'lingo-manager-pricing-detail' agenda_pricing.pricing.pk %}" class="link-action-icon link">{% trans "see" %}</a>
53
        </li>
54
      {% endfor %}
55
      </ul>
56
      {% else %}
57
      <div class="big-msg-info">
58
        {% blocktrans %}
59
        This agenda doesn't have any flat fee schedule pricing defined yet.
60
        {% endblocktrans %}
61
      </div>
62
      {% endif %}
45 63
    </div>
46 64

  
47 65
    <div aria-labelledby="tab-check" hidden="" id="panel-check" role="tabpanel" tabindex="0">
lingo/pricing/views.py
683 683

  
684 684
    def get_context_data(self, **kwargs):
685 685
        kwargs['agenda_pricings'] = (
686
            AgendaPricing.objects.filter(agendas=self.agenda)
686
            AgendaPricing.objects.filter(agendas=self.agenda, flat_fee_schedule=False)
687
            .select_related('pricing')
688
            .order_by('date_start', 'date_end')
689
        )
690
        kwargs['agenda_pricings_flat'] = (
691
            AgendaPricing.objects.filter(agendas=self.agenda, flat_fee_schedule=True)
687 692
            .select_related('pricing')
688 693
            .order_by('date_start', 'date_end')
689 694
        )
tests/pricing/manager/test_agenda_pricing.py
125 125
    assert resp.location.endswith('/manage/pricing/agenda-pricing/%s/' % agenda_pricing.pk)
126 126

  
127 127

  
128
def test_edit_agenda_pricing_overlapping_flat_fee_schedule(app, admin_user):
129
    agenda1 = Agenda.objects.create(label='Foo bar 1')
130
    agenda2 = Agenda.objects.create(label='Foo bar 2')
131
    pricing = Pricing.objects.create(label='Model')
132
    agenda_pricing1 = AgendaPricing.objects.create(
133
        label='Foo Bar',
134
        pricing=pricing,
135
        date_start=datetime.date(year=2021, month=9, day=1),
136
        date_end=datetime.date(year=2022, month=9, day=1),
137
    )
138
    agenda_pricing1.agendas.add(agenda1, agenda2)
139
    agenda_pricing2 = AgendaPricing.objects.create(
140
        label='Foo Bar',
141
        pricing=pricing,
142
        date_start=datetime.date(year=2021, month=9, day=1),
143
        date_end=datetime.date(year=2022, month=9, day=1),
144
    )
145
    agenda_pricing2.agendas.add(agenda1, agenda2)
146

  
147
    app = login(app)
148
    resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
149
    # ok, flat_fee_schedule has not changed
150
    resp.form.submit().follow()
151

  
152
    resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
153
    # ok, flat_fee_schedule is different
154
    resp.form['flat_fee_schedule'] = True
155
    resp.form.submit().follow()
156

  
157
    resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
158
    resp.form['flat_fee_schedule'] = False
159
    resp = resp.form.submit()
160
    assert resp.context['form'].non_field_errors() == [
161
        'Agenda "Foo bar 1" has already a pricing overlapping this period.',
162
        'Agenda "Foo bar 2" has already a pricing overlapping this period.',
163
    ]
164
    agenda_pricing2.agendas.remove(agenda1)
165
    resp = resp.form.submit()
166
    assert resp.context['form'].non_field_errors() == [
167
        'Agenda "Foo bar 2" has already a pricing overlapping this period.'
168
    ]
169
    agenda_pricing2.agendas.remove(agenda2)
170
    # ok
171
    resp.form.submit().follow()
172

  
173

  
174
def test_edit_agenda_pricing_overlapping_date_start(app, admin_user):
175
    agenda1 = Agenda.objects.create(label='Foo bar 1')
176
    agenda2 = Agenda.objects.create(label='Foo bar 2')
177
    pricing = Pricing.objects.create(label='Model')
178
    agenda_pricing1 = AgendaPricing.objects.create(
179
        label='Foo Bar',
180
        pricing=pricing,
181
        date_start=datetime.date(year=2021, month=10, day=1),
182
        date_end=datetime.date(year=2022, month=10, day=1),
183
    )
184
    agenda_pricing1.agendas.add(agenda1, agenda2)
185
    agenda_pricing2 = AgendaPricing.objects.create(
186
        label='Foo Bar',
187
        pricing=pricing,
188
        date_start=datetime.date(year=2021, month=9, day=1),
189
        date_end=datetime.date(year=2022, month=9, day=1),
190
    )
191
    agenda_pricing2.agendas.add(agenda1, agenda2)
192

  
193
    app = login(app)
194
    resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
195
    # ok, date_start has not changed
196
    resp.form.submit().follow()
197

  
198
    resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
199
    # ok, no overlapping
200
    resp.form['date_start'] = '2022-09-01'
201
    resp.form.submit().follow()
202

  
203
    resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
204
    resp.form['date_start'] = '2021-10-01'
205
    resp = resp.form.submit()
206
    assert resp.context['form'].non_field_errors() == [
207
        'Agenda "Foo bar 1" has already a pricing overlapping this period.',
208
        'Agenda "Foo bar 2" has already a pricing overlapping this period.',
209
    ]
210
    agenda_pricing2.agendas.remove(agenda1)
211
    resp = resp.form.submit()
212
    assert resp.context['form'].non_field_errors() == [
213
        'Agenda "Foo bar 2" has already a pricing overlapping this period.'
214
    ]
215
    agenda_pricing2.agendas.remove(agenda2)
216
    # ok
217
    resp.form.submit().follow()
218

  
219

  
220
def test_edit_agenda_pricing_overlapping_date_end(app, admin_user):
221
    agenda1 = Agenda.objects.create(label='Foo bar 1')
222
    agenda2 = Agenda.objects.create(label='Foo bar 2')
223
    pricing = Pricing.objects.create(label='Model')
224
    agenda_pricing1 = AgendaPricing.objects.create(
225
        label='Foo Bar',
226
        pricing=pricing,
227
        date_start=datetime.date(year=2021, month=8, day=1),
228
        date_end=datetime.date(year=2022, month=8, day=1),
229
    )
230
    agenda_pricing1.agendas.add(agenda1, agenda2)
231
    agenda_pricing2 = AgendaPricing.objects.create(
232
        label='Foo Bar',
233
        pricing=pricing,
234
        date_start=datetime.date(year=2021, month=9, day=1),
235
        date_end=datetime.date(year=2022, month=9, day=1),
236
    )
237
    agenda_pricing2.agendas.add(agenda1, agenda2)
238

  
239
    app = login(app)
240
    resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
241
    # ok, date_end has not changed
242
    resp.form.submit().follow()
243

  
244
    resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
245
    # ok, no overlapping
246
    resp.form['date_end'] = '2021-09-01'
247
    resp.form.submit().follow()
248

  
249
    resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
250
    resp.form['date_end'] = '2022-08-01'
251
    resp = resp.form.submit()
252
    assert resp.context['form'].non_field_errors() == [
253
        'Agenda "Foo bar 1" has already a pricing overlapping this period.',
254
        'Agenda "Foo bar 2" has already a pricing overlapping this period.',
255
    ]
256
    agenda_pricing2.agendas.remove(agenda1)
257
    resp = resp.form.submit()
258
    assert resp.context['form'].non_field_errors() == [
259
        'Agenda "Foo bar 2" has already a pricing overlapping this period.'
260
    ]
261
    agenda_pricing2.agendas.remove(agenda2)
262
    # ok
263
    resp.form.submit().follow()
264

  
265

  
128 266
def test_detail_agenda_pricing(app, admin_user):
129 267
    pricing = Pricing.objects.create(label='Model')
130 268
    agenda_pricing = AgendaPricing.objects.create(
......
209 347
        'This agendas has already a pricing overlapping this period.'
210 348
    ]
211 349
    resp.form['agenda'] = agenda3.pk
212
    resp = resp.form.submit().follow()
350
    resp.form.submit().follow()
213 351
    assert list(agenda_pricing2.agendas.all()) == [agenda3]
214 352

  
353
    agenda_pricing.flat_fee_schedule = True
354
    agenda_pricing.save()
355
    resp = app.get('/manage/pricing/agenda-pricing/%s/agenda/add/' % agenda_pricing2.pk)
356
    assert list(resp.context['form'].fields['agenda'].queryset) == [
357
        agenda1,
358
        agenda2,
359
    ]
360
    resp.form['agenda'] = agenda1.pk
361
    resp.form.submit()
362
    assert list(agenda_pricing2.agendas.all()) == [agenda1, agenda3]
363

  
215 364
    agenda_pricing.subscription_required = False
216 365
    agenda_pricing.save()
217 366
    app.get('/manage/pricing/agenda-pricing/%s/agenda/add/' % agenda_pricing.pk, status=404)
218
-