feat: накидка по строке в таблице «Цена продажи» + минимальный CSV

Sale-таблица показывает LOT/Описание/Кол-во/Накидка,%/Цена вместо Estimate/
Склад/Конкуренты/Ручная цена; итоговая цена строки = база (raw estimate или
доля от общей «Ручная цена») × (Аплифт к estimate + своя Накидка%). Экспорт
CSV этой таблицы теперь выводит только LOT;Описание;Кол-во;Цена. Buy-таблица
и массовый экспорт по проекту не затронуты — новые поля запроса опциональны
и включаются только кнопкой «Экспорт CSV» у Sale-таблицы.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-09-15 16:39:54 +03:00
co-authored by Claude Sonnet 5
parent fb412a4227
commit 7263dd4572
5 changed files with 385 additions and 100 deletions
+18
View File
@@ -55,6 +55,15 @@ type ProjectExportOptionsRequest struct {
IncludeCompetitor bool `json:"include_competitor"`
Basis string `json:"basis"` // "fob" or "ddp"
SaleMarkup float64 `json:"sale_markup"` // DDP multiplier; 0 defaults to 1.3
ManualPrice *float64 `json:"manual_price"` // user-defined total price; distributed proportionally across rows
// MinimalSaleColumns/SaleRowMarkups are sent only by the single-config Sale-table
// "Экспорт CSV" button (index.html exportPricingCSV('sale')) — never by the Buy
// export or the project-level bulk export, which always leave these zero-valued so
// their output stays unchanged. See services.ProjectPricingExportOptions.
MinimalSaleColumns bool `json:"minimal_sale_columns"`
SaleRowMarkups map[string]float64 `json:"sale_row_markups"` // "<vendorPN>::<lot>" -> markup percent
}
func (h *ExportHandler) ExportCSV(c *gin.Context) {
@@ -254,6 +263,15 @@ func (h *ExportHandler) ExportConfigPricingCSV(c *gin.Context) {
Basis: req.Basis,
SaleMarkup: req.SaleMarkup,
}
// MinimalSaleColumns/SaleRowMarkups/ManualPrice are only ever sent by the Sale
// table's own "Экспорт CSV" button (index.html exportPricingCSV('sale')) — gating
// on the request's own flag keeps every other caller (Buy export, any other basis=
// ddp caller) byte-identical to before this field existed.
if req.MinimalSaleColumns {
opts.MinimalSaleColumns = true
opts.SaleRowMarkups = req.SaleRowMarkups
opts.ManualPrice = req.ManualPrice
}
data, err := h.exportService.ConfigToPricingExportData(config, opts)
if err != nil {