release: «Мой налог» tax export (v1.27.0) #296
@@ -661,6 +661,11 @@ func TestMyNalogBuyerMails(t *testing.T) {
|
|||||||
if !strings.Contains(first[0].Text, "не чек") {
|
if !strings.Contains(first[0].Text, "не чек") {
|
||||||
t.Errorf("the purchase letter does not say it is not the receipt:\n%s", first[0].Text)
|
t.Errorf("the purchase letter does not say it is not the receipt:\n%s", first[0].Text)
|
||||||
}
|
}
|
||||||
|
// The catalog title already names the pack size, so appending it again read as
|
||||||
|
// "50 фишек — 50 фишек". The line is the title verbatim, then the price, and nothing else.
|
||||||
|
if !strings.Contains(first[0].Text, "Покупка совершена: test pack, 149.00 ₽.") {
|
||||||
|
t.Errorf("the purchase line is not the catalog title plus the price:\n%s", first[0].Text)
|
||||||
|
}
|
||||||
|
|
||||||
// 2. The receipt letter, once the income is filed, carrying the printable link.
|
// 2. The receipt letter, once the income is filed, carrying the printable link.
|
||||||
if _, err := exp.RunBatch(ctx, time.Minute); err != nil {
|
if _, err := exp.RunBatch(ctx, time.Minute); err != nil {
|
||||||
|
|||||||
@@ -185,15 +185,18 @@ func (m *Mailer) stampReceipt(ctx context.Context, mark func(context.Context, uu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// describe renders what was bought in one line.
|
// describe renders what was bought in one line: the catalog title exactly as the buyer saw it on
|
||||||
func describe(title string, chips int, amountMinor int64, currency string) string {
|
// the storefront, then the price.
|
||||||
|
//
|
||||||
|
// The pack size is deliberately NOT appended. Catalog titles already name it ("50 фишек"), so
|
||||||
|
// adding it produced "50 фишек — 50 фишек". The title is the single source of that wording; the
|
||||||
|
// tax receipt states the quantity separately in the form the tax service wants (see
|
||||||
|
// mynalog.IncomeName), which is a different surface with different requirements.
|
||||||
|
func describe(title string, amountMinor int64, currency string) string {
|
||||||
what := strings.TrimSpace(title)
|
what := strings.TrimSpace(title)
|
||||||
if what == "" {
|
if what == "" {
|
||||||
what = "покупка в игре"
|
what = "покупка в игре"
|
||||||
}
|
}
|
||||||
if chips > 0 {
|
|
||||||
what = fmt.Sprintf("%s — %d фишек", what, chips)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s, %s", what, formatAmount(amountMinor, currency))
|
return fmt.Sprintf("%s, %s", what, formatAmount(amountMinor, currency))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +227,7 @@ func purchaseText(p payments.PurchaseMail) string {
|
|||||||
отдельным письмом: обычно в течение часа, но иногда это занимает до нескольких дней.
|
отдельным письмом: обычно в течение часа, но иногда это занимает до нескольких дней.
|
||||||
|
|
||||||
Спасибо, что играете в «Эрудит».
|
Спасибо, что играете в «Эрудит».
|
||||||
`, describe(p.Title, p.Chips, p.AmountMinor, p.Currency), p.OrderID)
|
`, describe(p.Title, p.AmountMinor, p.Currency), p.OrderID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// receiptText is the fiscal receipt letter, which is how the receipt is actually handed to the
|
// receiptText is the fiscal receipt letter, which is how the receipt is actually handed to the
|
||||||
@@ -240,7 +243,7 @@ func receiptText(r payments.ReceiptMail, inn, baseURL string, loc *time.Location
|
|||||||
|
|
||||||
Продавец применяет налог на профессиональный доход; чек сформирован в сервисе
|
Продавец применяет налог на профессиональный доход; чек сформирован в сервисе
|
||||||
«Мой налог» Федеральной налоговой службы.
|
«Мой налог» Федеральной налоговой службы.
|
||||||
`, describe(r.Title, r.Chips, r.AmountMinor, r.Currency),
|
`, describe(r.Title, r.AmountMinor, r.Currency),
|
||||||
r.OperationTime.In(loc).Format("02.01.2006 15:04"),
|
r.OperationTime.In(loc).Format("02.01.2006 15:04"),
|
||||||
mynalog.ReceiptURL(baseURL, inn, r.ReceiptUUID))
|
mynalog.ReceiptURL(baseURL, inn, r.ReceiptUUID))
|
||||||
}
|
}
|
||||||
@@ -255,6 +258,6 @@ func cancelText(r payments.ReceiptMail, loc *time.Location) string {
|
|||||||
|
|
||||||
%s
|
%s
|
||||||
Дата покупки: %s
|
Дата покупки: %s
|
||||||
`, describe(r.Title, r.Chips, r.AmountMinor, r.Currency),
|
`, describe(r.Title, r.AmountMinor, r.Currency),
|
||||||
r.OperationTime.In(loc).Format("02.01.2006 15:04"))
|
r.OperationTime.In(loc).Format("02.01.2006 15:04"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,7 +125,6 @@ type PurchaseMail struct {
|
|||||||
OrderID uuid.UUID
|
OrderID uuid.UUID
|
||||||
Origin string
|
Origin string
|
||||||
Title string
|
Title string
|
||||||
Chips int
|
|
||||||
AmountMinor int64
|
AmountMinor int64
|
||||||
Currency string
|
Currency string
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
@@ -137,7 +136,6 @@ type ReceiptMail struct {
|
|||||||
AccountID uuid.UUID
|
AccountID uuid.UUID
|
||||||
ReceiptUUID string
|
ReceiptUUID string
|
||||||
Title string
|
Title string
|
||||||
Chips int
|
|
||||||
AmountMinor int64
|
AmountMinor int64
|
||||||
Currency string
|
Currency string
|
||||||
OperationTime time.Time
|
OperationTime time.Time
|
||||||
|
|||||||
@@ -476,7 +476,7 @@ func (s *Store) pendingPurchaseMails(ctx context.Context, limit int) ([]Purchase
|
|||||||
rows, err := s.db.QueryContext(ctx, `
|
rows, err := s.db.QueryContext(ctx, `
|
||||||
SELECT e.event_id, e.account_id, e.order_id, COALESCE(o.origin, ''),
|
SELECT e.event_id, e.account_id, e.order_id, COALESCE(o.origin, ''),
|
||||||
COALESCE(o.expected_amount, 0), COALESCE(o.currency, ''),
|
COALESCE(o.expected_amount, 0), COALESCE(o.currency, ''),
|
||||||
COALESCE(p.title, ''), COALESCE((e.payload->>'chips')::int, 0), e.created_at
|
COALESCE(p.title, ''), e.created_at
|
||||||
FROM payments.payment_events e
|
FROM payments.payment_events e
|
||||||
LEFT JOIN payments.orders o ON o.order_id = e.order_id
|
LEFT JOIN payments.orders o ON o.order_id = e.order_id
|
||||||
LEFT JOIN payments.product p ON p.product_id = o.product_id
|
LEFT JOIN payments.product p ON p.product_id = o.product_id
|
||||||
@@ -495,7 +495,7 @@ func (s *Store) pendingPurchaseMails(ctx context.Context, limit int) ([]Purchase
|
|||||||
orderID uuid.NullUUID
|
orderID uuid.NullUUID
|
||||||
)
|
)
|
||||||
if err := rows.Scan(&m.EventID, &m.AccountID, &orderID, &m.Origin, &m.AmountMinor,
|
if err := rows.Scan(&m.EventID, &m.AccountID, &orderID, &m.Origin, &m.AmountMinor,
|
||||||
&m.Currency, &m.Title, &m.Chips, &m.CreatedAt); err != nil {
|
&m.Currency, &m.Title, &m.CreatedAt); err != nil {
|
||||||
return nil, fmt.Errorf("payments: scan purchase mail: %w", err)
|
return nil, fmt.Errorf("payments: scan purchase mail: %w", err)
|
||||||
}
|
}
|
||||||
m.OrderID = orderID.UUID
|
m.OrderID = orderID.UUID
|
||||||
@@ -551,7 +551,7 @@ func (s *Store) pendingMyNalogMails(ctx context.Context, limit int, cancelled bo
|
|||||||
&m.AmountMinor, &m.Currency, &m.OperationTime); err != nil {
|
&m.AmountMinor, &m.Currency, &m.OperationTime); err != nil {
|
||||||
return nil, fmt.Errorf("payments: scan receipt mail: %w", err)
|
return nil, fmt.Errorf("payments: scan receipt mail: %w", err)
|
||||||
}
|
}
|
||||||
m.Title, m.Chips = describeSnapshot(snapshot.String)
|
m.Title, _ = describeSnapshot(snapshot.String)
|
||||||
out = append(out, m)
|
out = append(out, m)
|
||||||
}
|
}
|
||||||
if err := rows.Err(); err != nil {
|
if err := rows.Err(); err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user