Списки: период, сортировка, подгрузка; анкета участника — строкой исходящих
«Исходящие», «Входящие», «Журнал обмена»: быстрые периоды (сегодня, 7, 30 дней, всё время), даты с–по, сортировка (время, инвестор/контрагент, направление, статус), первые 50 строк и подгрузка при прокрутке (part=rows&offset=N). Раньше показывались только последние 200/100. Анкета участника — исходящий пакет в НРД: строка в «Исходящих» и «Журнале» с ответом НРД (принята / отклонена с кодом / ждёт), вместо плашки над списком. Отправки копятся в participant-regs.json (прежний participant-reg.json подхватывается). userTemplate — функции текущего пользователя и для порций строк. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
@@ -31,35 +31,93 @@ type participantReg struct {
|
||||
|
||||
var participantRegMu sync.Mutex
|
||||
|
||||
func loadParticipantReg() participantReg {
|
||||
participantRegMu.Lock()
|
||||
defer participantRegMu.Unlock()
|
||||
var r participantReg
|
||||
if b, err := os.ReadFile(participantRegFile); err == nil {
|
||||
_ = json.Unmarshal(b, &r)
|
||||
// participantRegsFile — все отправки анкеты (строки в «Исходящих» и «Журнале»); participantRegFile —
|
||||
// прежний файл с одной последней отправкой, из него история начинается при первом чтении.
|
||||
const participantRegsFile = "/var/lib/bj/.bj/participant-regs.json"
|
||||
|
||||
func readParticipantRegs() []participantReg {
|
||||
var list []participantReg
|
||||
if b, err := os.ReadFile(participantRegsFile); err == nil {
|
||||
_ = json.Unmarshal(b, &list)
|
||||
return list
|
||||
}
|
||||
return r
|
||||
var r participantReg
|
||||
if b, err := os.ReadFile(participantRegFile); err == nil && json.Unmarshal(b, &r) == nil && !r.SentAt.IsZero() {
|
||||
list = append(list, r)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// saveParticipantReg читает текущую запись, даёт изменить и атомарно пишет назад.
|
||||
func saveParticipantReg(mut func(*participantReg)) {
|
||||
participantRegMu.Lock()
|
||||
defer participantRegMu.Unlock()
|
||||
var r participantReg
|
||||
if b, err := os.ReadFile(participantRegFile); err == nil {
|
||||
_ = json.Unmarshal(b, &r)
|
||||
}
|
||||
mut(&r)
|
||||
b, err := json.MarshalIndent(&r, "", " ")
|
||||
func writeParticipantRegs(list []participantReg) {
|
||||
b, err := json.MarshalIndent(list, "", " ")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tmp := participantRegFile + ".tmp"
|
||||
tmp := participantRegsFile + ".tmp"
|
||||
if os.WriteFile(tmp, b, 0o640) == nil {
|
||||
_ = os.Rename(tmp, participantRegFile)
|
||||
_ = os.Rename(tmp, participantRegsFile)
|
||||
}
|
||||
}
|
||||
|
||||
// loadParticipantRegs — все отправки анкеты, старые первыми.
|
||||
func loadParticipantRegs() []participantReg {
|
||||
participantRegMu.Lock()
|
||||
defer participantRegMu.Unlock()
|
||||
return readParticipantRegs()
|
||||
}
|
||||
|
||||
// loadParticipantReg — последняя отправка анкеты.
|
||||
func loadParticipantReg() participantReg {
|
||||
list := loadParticipantRegs()
|
||||
if len(list) == 0 {
|
||||
return participantReg{}
|
||||
}
|
||||
return list[len(list)-1]
|
||||
}
|
||||
|
||||
// addParticipantReg — новая отправка анкеты.
|
||||
func addParticipantReg(r participantReg) {
|
||||
participantRegMu.Lock()
|
||||
defer participantRegMu.Unlock()
|
||||
writeParticipantRegs(append(readParticipantRegs(), r))
|
||||
}
|
||||
|
||||
// saveParticipantReg — изменить последнюю отправку (ответ НРД приходит на неё).
|
||||
func saveParticipantReg(mut func(*participantReg)) {
|
||||
participantRegMu.Lock()
|
||||
defer participantRegMu.Unlock()
|
||||
list := readParticipantRegs()
|
||||
if len(list) == 0 {
|
||||
list = append(list, participantReg{})
|
||||
}
|
||||
mut(&list[len(list)-1])
|
||||
writeParticipantRegs(list)
|
||||
}
|
||||
|
||||
// StatusClass, StatusText — статус отправки анкеты для строк списков (класс бейджа и текст).
|
||||
func (r participantReg) StatusClass() string {
|
||||
switch {
|
||||
case r.RespAt.IsZero():
|
||||
return "awaiting_decision"
|
||||
case strings.EqualFold(r.Status, "ERROR"):
|
||||
return "rejected"
|
||||
}
|
||||
return "confirmed"
|
||||
}
|
||||
|
||||
func (r participantReg) StatusText() string {
|
||||
switch {
|
||||
case r.RespAt.IsZero():
|
||||
return "Ждёт ответа НРД"
|
||||
case strings.EqualFold(r.Status, "ERROR"):
|
||||
if len(r.Codes) > 0 {
|
||||
return "Отклонена НРД · " + strings.Join(r.Codes, ", ")
|
||||
}
|
||||
return "Отклонена НРД"
|
||||
}
|
||||
return "Принята НРД"
|
||||
}
|
||||
|
||||
// recordParticipantReply сохраняет ответ НРД на анкету (статус, коды, тексты, файл XML).
|
||||
func recordParticipantReply(status string, resp *m2m.M2MTransferResponse, rawFile string) {
|
||||
var codes []string
|
||||
|
||||
Reference in New Issue
Block a user