Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(PC-31820)[BO] fix: manage price category when editing stock in BO #14220

Merged
merged 1 commit into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 61 additions & 20 deletions api/src/pcapi/routes/backoffice/offers/blueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -898,10 +898,51 @@ def _is_stock_editable(offer_id: int, stock_id: int) -> bool:
return stock_id in _get_editable_stock(offer_id)


def _manage_price_category(stock: offers_models.Stock, new_price: float) -> bool:
if stock.priceCategory is None:
return False

stock_count = (
db.session.query(sa.func.count(offers_models.Stock.id))
.filter(offers_models.Stock.priceCategoryId == stock.priceCategoryId)
.scalar()
)

if stock_count == 1:
stock.priceCategory.price = new_price
db.session.add(stock.priceCategory)
return False

new_price_category_label = offers_models.PriceCategoryLabel(
label=f"{stock.priceCategory.priceCategoryLabel.label} - Revalorisation du {datetime.date.today().strftime('%d/%m/%Y')}",
prouzet marked this conversation as resolved.
Show resolved Hide resolved
venue=stock.priceCategory.priceCategoryLabel.venue,
)
db.session.add(new_price_category_label)
new_price_category = offers_models.PriceCategory(
offerId=stock.offerId,
price=decimal.Decimal(new_price),
priceCategoryLabel=new_price_category_label,
)
db.session.add(new_price_category)
stock.priceCategory = new_price_category
db.session.add(stock)
return True


@list_offers_blueprint.route("/<int:offer_id>/stock/<int:stock_id>/edit", methods=["POST"])
@utils.permission_required(perm_models.Permissions.MANAGE_OFFERS)
def edit_offer_stock(offer_id: int, stock_id: int) -> utils.BackofficeResponse:
stock = offers_models.Stock.query.filter_by(id=stock_id).one()
stock = (
offers_models.Stock.query.filter(
offers_models.Stock.id == stock_id,
)
.options(
sa.orm.joinedload(offers_models.Stock.priceCategory).joinedload(
offers_models.PriceCategory.priceCategoryLabel
),
)
.one()
)

if stock.offerId != offer_id:
flash("L'offer_id et le stock_id ne sont pas cohérents.", "warning")
Expand All @@ -920,31 +961,31 @@ def edit_offer_stock(offer_id: int, stock_id: int) -> utils.BackofficeResponse:
flash(utils.build_form_error_msg(form), "warning")
return redirect(url_for("backoffice_web.offer.get_offer_details", offer_id=offer_id), 303)

new_price = 0.0
if form.price.data:
new_price = float(form.price.data)
offers_api.update_used_stock_price(stock=stock, new_price=form.price.data)
logger.info(
"A past stock price was updated by an administrator",
extra={
"user_id": current_user.id,
"stock_id": stock_id,
"old_price": float(old_price),
"new_price": float(form.price.data),
},
)

if form.percent.data:
price_percent = decimal.Decimal((100 - float(form.percent.data)) / 100)
new_price = stock.price * price_percent
offers_api.update_used_stock_price(stock=stock, price_percent=price_percent)
logger.info(
"A past stock price was updated by an administrator",
extra={
"user_id": current_user.id,
"stock_id": stock_id,
"old_price": float(old_price),
"new_price": float(round(old_price * price_percent, 2)),
},
)

flash(f"Le stock {stock_id} a été mis à jour.", "success")
db.session.flush()
if _manage_price_category(stock, new_price):
flash(f"Le stock {stock_id} a été mis à jour et un nouveau tarif a été créé", "success")
else:
flash(f"Le stock {stock_id} a été mis à jour.", "success")
logger.info(
"A past stock price was updated by an administrator",
extra={
"user_id": current_user.id,
"stock_id": stock_id,
"old_price": float(old_price),
"new_price": float(new_price),
},
)

db.session.commit()
return redirect(url_for("backoffice_web.offer.get_offer_details", offer_id=offer_id), 303)

Expand Down
72 changes: 72 additions & 0 deletions api/tests/routes/backoffice/offers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2898,6 +2898,78 @@ def test_edit_stock_withprice_higher_than_booking(self, authenticated_client):
assert event.booking.stock.price == decimal.Decimal("10.00")
assert event.booking.amount == decimal.Decimal("5.00")

def test_offer_stock_edit_with_price_category(self, authenticated_client):
price_category = offers_factories.PriceCategoryFactory(
offer__subcategoryId=subcategories.CONFERENCE.id,
price=decimal.Decimal("123.45"),
)
label = price_category.priceCategoryLabel.label
offer = price_category.offer
stock_to_edit = offers_factories.StockFactory(
offer=offer,
price=decimal.Decimal("123.45"),
priceCategory=price_category,
)
booking_to_edit = bookings_factories.UsedBookingFactory(
stock=stock_to_edit,
amount=decimal.Decimal("123.45"),
)

response = self.post_to_endpoint(
authenticated_client, offer_id=offer.id, stock_id=stock_to_edit.id, form={"price": "50.1"}
)

db.session.expire_all()

assert response.status_code == 303

assert stock_to_edit.price == decimal.Decimal("50.1")
assert booking_to_edit.amount == decimal.Decimal("50.1")
assert price_category.price == decimal.Decimal("50.1")
assert price_category.priceCategoryLabel.label == label
assert stock_to_edit.priceCategory == price_category

def test_offer_stock_edit_with_price_category_with_multiple_stocks(self, authenticated_client):
price_category = offers_factories.PriceCategoryFactory(
offer__subcategoryId=subcategories.CONFERENCE.id,
price=decimal.Decimal("123.45"),
)
label = price_category.priceCategoryLabel.label
offer = price_category.offer
stock_to_edit = offers_factories.StockFactory(
offer=offer,
price=decimal.Decimal("123.45"),
priceCategory=price_category,
)
other_stock = offers_factories.StockFactory(
offer=offer,
price=decimal.Decimal("123.45"),
priceCategory=price_category,
)
booking_to_edit = bookings_factories.UsedBookingFactory(
stock=stock_to_edit,
amount=decimal.Decimal("123.45"),
)

response = self.post_to_endpoint(
authenticated_client, offer_id=offer.id, stock_id=stock_to_edit.id, form={"price": "50.1"}
)

db.session.expire_all()

assert response.status_code == 303
expected_label = f"{label} - Revalorisation du {datetime.date.today().strftime('%d/%m/%Y')}"
assert stock_to_edit.price == decimal.Decimal("50.1")
assert booking_to_edit.amount == decimal.Decimal("50.1")
assert stock_to_edit.priceCategory != price_category
assert stock_to_edit.priceCategory.price == decimal.Decimal("50.1")
assert stock_to_edit.priceCategory.priceCategoryLabel.label == expected_label

assert other_stock.price == decimal.Decimal("123.45")
assert other_stock.priceCategory == price_category
assert other_stock.priceCategory.price == decimal.Decimal("123.45")
assert other_stock.priceCategory.priceCategoryLabel.label == label


class DownloadBookingsCSVTest(GetEndpointHelper):
endpoint = "backoffice_web.offer.download_bookings_csv"
Expand Down
Loading