public CashierPaymentDetail(CashierPayment payment)
 {
     Id          = payment.Id;
     CashEntered = payment.CashEntered;
     Change      = payment.Change;
     Session     = new SessionDetail {
         Id = payment.Session.Id
     };
     Invoice = new InvoiceDetail {
         Id = payment.Invoice.Id, Number = payment.Invoice.Number
     };
 }
Esempio n. 2
0
 public InvoiceDetail(Invoice invoice, CashierPayment payment = null)
 {
     Id             = invoice.Id;
     Number         = invoice.Number;
     OriginalPrice  = invoice.OriginalPrice;
     FinalPrice     = invoice.FinalPrice;
     Discount       = invoice.Discount;
     PaidWithPoints = invoice.PaidWithPoints;
     Points         = invoice.Points;
     Note           = invoice.Note;
     Customer       = new CustomerDetail(invoice.Customer);
     InvoiceItems   = new List <InvoiceItemDetail>
                          (invoice.InvoiceItems.Select(i => new InvoiceItemDetail(i)));
     if (payment != null)
     {
         CashierPayment = new CashierPaymentDetail(payment);
     }
 }
        public async Task <EntityApiResponse <InvoiceDetail> > AddInvoiceAsync(InvoiceDetail invoiceDetail, string currentUserId)
        {
            if (invoiceDetail is null)
            {
                throw new ArgumentNullException(nameof(invoiceDetail));
            }

            if (invoiceDetail.InvoiceItems is null || invoiceDetail.InvoiceItems.Count < 1)
            {
                return(new EntityApiResponse <InvoiceDetail>(error: "Invoice has no items"));
            }

            if (invoiceDetail.InvoiceItems.Any(item => item.Quantity < 1))
            {
                return(new EntityApiResponse <InvoiceDetail>(error: "Invoice can't have an item with quantity zero"));
            }

            var org = await _orgRepository.GetByIdAsync(invoiceDetail.OrganizationId);

            if (org is null)
            {
                return(new EntityApiResponse <InvoiceDetail>(error: "Organization does not exist"));
            }

            Customer customer = null;

            var belongToCustomer = !(invoiceDetail.Customer is null);
            var paidWithPoints   = invoiceDetail.PaidWithPoints > 0;

            if (belongToCustomer)
            {
                customer = await _customerRepository.GetByIdAsync(invoiceDetail.Customer.Id);

                if (customer is null)
                {
                    return(new EntityApiResponse <InvoiceDetail>(error: "Customer does not exist"));
                }

                if (paidWithPoints && customer.Points < invoiceDetail.PaidWithPoints)
                {
                    return(new EntityApiResponse <InvoiceDetail>(error: "Customer doesn't have enough points"));
                }

                if (paidWithPoints && !_settings.PointsValues.TryGetValue(invoiceDetail.PaidWithPoints, out var amount))
                {
                    return(new EntityApiResponse <InvoiceDetail>(error: $"{invoiceDetail.PaidWithPoints} points are not a standard exchangement"));
                }
            }

            // Check if the current user is in his specified session
            var now = DateTime.UtcNow;

            Session session = null;

            if (_settings.RestrictPaymentOnSession)
            {
                session = await _sessionRepository.Table
                          .FirstOrDefaultAsync(s => now >= s.StartDate && now <= s.EndDate && s.UserId == currentUserId);

                if (session is null)
                {
                    return(new EntityApiResponse <InvoiceDetail>(error: "Can't add invoice, current session belongs to another user"));
                }
            }

            var newInvoiceNumber = org.LastInvoiceNumber + 1;
            var invoicePoints    = 0;

            var invoice = new Invoice
            {
                Number         = newInvoiceNumber,
                Discount       = invoiceDetail.Discount,
                OrganizationId = org.Id,
                CreatedById    = currentUserId,
                ModifiedById   = currentUserId,
                OriginalPrice  = invoiceDetail.OriginalPrice,
                FinalPrice     = invoiceDetail.FinalPrice,
                Note           = invoiceDetail.Note?.Trim(),
                CustomerId     = customer?.Id
            };

            await _invoiceRepository.InsertAsync(invoice);

            foreach (var item in invoiceDetail.InvoiceItems)
            {
                var stock = await _stockRepository.GetByIdAsync(item.Stock?.Id);

                if (stock is null)
                {
                    continue;
                }

                var newInvoiceItem = new InvoiceItem
                {
                    Description    = item.Description?.Trim(),
                    Quantity       = item.Quantity,
                    Price          = item.Price,
                    FinalPrice     = item.FinalPrice,
                    Discount       = item.Discount,
                    CreatedById    = currentUserId,
                    ModifiedById   = currentUserId,
                    OrganizationId = org.Id,
                    StockId        = stock.Id,
                    InvoiceId      = invoice.Id
                };

                await _invoiceItemRepository.InsertAsync(newInvoiceItem);

                stock.Quantity        -= newInvoiceItem.Quantity;
                stock.LastModifiedDate = DateTime.UtcNow;
                stock.ModifiedById     = currentUserId;

                await _stockRepository.UpdateAsync(stock);

                invoicePoints += stock.Points * newInvoiceItem.Quantity;
            }

            // Check points for updating customer's balance
            if (belongToCustomer)
            {
                customer.Points += invoicePoints;
                if (paidWithPoints)
                {
                    customer.Points -= invoiceDetail.PaidWithPoints;
                }

                await _customerRepository.UpdateAsync(customer);
            }

            var payment = new CashierPayment
            {
                CashEntered    = invoiceDetail.CashierPayment?.CashEntered ?? 0m,
                Change         = invoiceDetail.CashierPayment?.Change ?? 0m,
                SessionId      = session?.Id,
                OrganizationId = org.Id,
                InvoiceId      = invoice.Id,
                CreatedById    = currentUserId,
                ModifiedById   = currentUserId
            };

            await _paymentRepository.InsertAsync(payment);

            invoice.Points = invoicePoints;
            await _invoiceRepository.UpdateAsync(invoice);

            org.LastInvoiceNumber += 1;
            await _orgRepository.UpdateAsync(org);

            return(new EntityApiResponse <InvoiceDetail>(entity: new InvoiceDetail(invoice, payment)));
        }