public async Task Should_Publish_Refund_Payment_Event()
        {
            // Arrange
            var request = new CreateEShopRefundInput
            {
                DisplayReason  = "Reason",
                CustomerRemark = "Customer Remark",
                PaymentId      = PaymentsTestData.Payment1,
                StaffRemark    = "StaffRemark",
                RefundItems    = new List <CreateEShopRefundItemInput>
                {
                    new CreateEShopRefundItemInput
                    {
                        CustomerRemark = "CustomerRemark",
                        OrderId        = PaymentsTestData.Order1,
                        StaffRemark    = "StaffRemark",
                        OrderLines     = new List <OrderLineRefundInfoModel>
                        {
                            new OrderLineRefundInfoModel
                            {
                                OrderLineId = PaymentsTestData.OrderLine1,
                                Quantity    = 1,
                                TotalAmount = 0
                            }
                        }
                    }
                }
            };

            // Act & Assert
            await _refundAppService.CreateAsync(request);

            _testRefundPaymentEventHandler.IsEventPublished.ShouldBe(true);
        }
Exemple #2
0
        public virtual async Task CreateAsync(CreateEShopRefundInput input)
        {
            await AuthorizationService.CheckAsync(PaymentsPermissions.Refunds.Manage);

            var payment = await _paymentRepository.GetAsync(input.PaymentId);

            var createRefundInput = new CreateRefundInput
            {
                PaymentId      = input.PaymentId,
                DisplayReason  = input.DisplayReason,
                CustomerRemark = input.CustomerRemark,
                StaffRemark    = input.StaffRemark
            };

            foreach (var refundItem in input.RefundItems)
            {
                var order = await _orderAppService.GetAsync(refundItem.OrderId);

                var paymentItem = payment.PaymentItems.SingleOrDefault(x => x.ItemKey == refundItem.OrderId.ToString());

                if (order.PaymentId != input.PaymentId || paymentItem == null)
                {
                    throw new OrderIsNotInSpecifiedPaymentException(order.Id, payment.Id);
                }

                // Todo: Check if current user is an admin of the store.

                foreach (var orderLineRefundInfoModel in refundItem.OrderLines)
                {
                    var orderLine = order.OrderLines.Single(x => x.Id == orderLineRefundInfoModel.OrderLineId);

                    if (orderLine.RefundedQuantity + orderLineRefundInfoModel.Quantity > orderLine.Quantity)
                    {
                        throw new InvalidRefundQuantityException(orderLineRefundInfoModel.Quantity);
                    }
                }

                createRefundInput.RefundItems.Add(new CreateRefundItemInput
                {
                    PaymentItemId   = paymentItem.Id,
                    RefundAmount    = refundItem.OrderLines.Sum(x => x.TotalAmount),
                    CustomerRemark  = refundItem.CustomerRemark,
                    StaffRemark     = refundItem.StaffRemark,
                    ExtraProperties = new Dictionary <string, object>
                    {
                        { "StoreId", order.StoreId.ToString() },
                        { "OrderId", order.Id.ToString() },
                        { "OrderLines", _jsonSerializer.Serialize(refundItem.OrderLines) }
                    }
                });
            }

            await _distributedEventBus.PublishAsync(new RefundPaymentEto
            {
                TenantId          = CurrentTenant.Id,
                CreateRefundInput = createRefundInput
            });
        }
 public Task CreateAsync(CreateEShopRefundInput input)
 {
     return(_service.CreateAsync(input));
 }
Exemple #4
0
        public virtual async Task CreateAsync(CreateEShopRefundInput input)
        {
            await AuthorizationService.CheckAsync(PaymentsPermissions.Refunds.Manage);

            var payment = await _paymentRepository.GetAsync(input.PaymentId);

            if (payment.PendingRefundAmount != decimal.Zero)
            {
                throw new AnotherRefundTaskIsOnGoingException(payment.Id);
            }

            var createRefundInput = new CreateRefundInput
            {
                PaymentId      = input.PaymentId,
                DisplayReason  = input.DisplayReason,
                CustomerRemark = input.CustomerRemark,
                StaffRemark    = input.StaffRemark
            };

            foreach (var refundItem in input.RefundItems)
            {
                var order = await _orderAppService.GetAsync(refundItem.OrderId);

                var paymentItem = payment.PaymentItems.SingleOrDefault(x => x.ItemKey == refundItem.OrderId.ToString());

                if (order.PaymentId != input.PaymentId || paymentItem == null)
                {
                    throw new OrderIsNotInSpecifiedPaymentException(order.Id, payment.Id);
                }

                await AuthorizationService.CheckMultiStorePolicyAsync(paymentItem.StoreId,
                                                                      PaymentsPermissions.Refunds.Manage, PaymentsPermissions.Refunds.CrossStore);

                var refundAmount = refundItem.OrderLines.Sum(x => x.TotalAmount) +
                                   refundItem.OrderExtraFees.Sum(x => x.TotalAmount);

                if (refundAmount + paymentItem.RefundAmount > paymentItem.ActualPaymentAmount)
                {
                    throw new InvalidRefundAmountException(payment.Id, paymentItem.Id, refundAmount);
                }

                foreach (var model in refundItem.OrderLines)
                {
                    var orderLine = order.OrderLines.Find(x => x.Id == model.OrderLineId);

                    if (orderLine is null)
                    {
                        throw new OrderLineNotFoundException(order.Id, model.OrderLineId);
                    }

                    if (orderLine.RefundedQuantity + model.Quantity > orderLine.Quantity)
                    {
                        throw new InvalidRefundQuantityException(model.Quantity);
                    }
                }

                foreach (var model in refundItem.OrderExtraFees)
                {
                    var orderExtraFee = order.OrderExtraFees.Find(x => x.Name == model.Name && x.Key == model.Key);

                    if (orderExtraFee is null)
                    {
                        throw new OrderExtraFeeNotFoundException(order.Id, model.Name, model.Key);
                    }
                }

                var eto = new CreateRefundItemInput
                {
                    PaymentItemId  = paymentItem.Id,
                    RefundAmount   = refundAmount,
                    CustomerRemark = refundItem.CustomerRemark,
                    StaffRemark    = refundItem.StaffRemark
                };

                eto.SetProperty(nameof(RefundItem.StoreId), order.StoreId);
                eto.SetProperty(nameof(RefundItem.OrderId), order.Id);
                eto.SetProperty(nameof(RefundItem.OrderLines), _jsonSerializer.Serialize(refundItem.OrderLines));
                eto.SetProperty(nameof(RefundItem.OrderExtraFees), _jsonSerializer.Serialize(refundItem.OrderExtraFees));

                createRefundInput.RefundItems.Add(eto);
            }

            await _distributedEventBus.PublishAsync(new RefundPaymentEto(CurrentTenant.Id, createRefundInput));
        }