#13: formular de facturare unificat - etapa curenta
Squash al branch-ului de lucru plan13-s2. Clase: ofacturare (nucleul formularului unificat), ofacturare_comun, ferestre_cere_date, ocomenzi, caut_ora (lista de preturi in combo-urile de cautare), omodificari. Programe: ofacturare impartit - ofacturare_antet, ofacturare_rutare_scriere si ogrid_latimi sunt fisiere noi; oproceduri_facturare primeste discountul pe linie si cota standard de TVA cand articolul nu are cota pe politica. Documentatie: capcana SQLExec no_data_found, conventia de encoding, depanarea testelor VFP si regulile de lucru - conflictele cu modificarile venite din alte proiecte sunt rezolvate pastrand ambele parti. Loguri de rulare a testelor scoase din versionare; testele raman. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PkyjGyrV2S7932om4kfSiK
This commit is contained in:
@@ -1 +1 @@
|
||||
2026-08-02
|
||||
2026-09-09
|
||||
|
||||
50
docs/capcana_sqlexec_no_data_found.md
Normal file
50
docs/capcana_sqlexec_no_data_found.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Capcana: linii pierdute tacut intre VFP si Oracle
|
||||
|
||||
## Simptomul
|
||||
|
||||
Un document se salveaza cu mai putine linii decat are pe ecran. Fara mesaj, fara eroare, fara
|
||||
nimic in log. Totalurile ies mai mici, dar consistente intre ele - deci nu arata a defect.
|
||||
|
||||
## Mecanismul, in doi pasi
|
||||
|
||||
1. Un `SELECT ... INTO` **fara handler** intr-o procedura PL/SQL arunca `ORA-01403`
|
||||
(`NO_DATA_FOUND`) cand predicatul nu potriveste niciun rand.
|
||||
2. ODBC il traduce ca `SQL_NO_DATA`, si **`SQLExec()` intoarce 1, adica succes**. Bucla din VFP
|
||||
testeaza `If lnSucces < 0` si nu vede nimic. Linia dispare fara urma.
|
||||
|
||||
Deci: eroare reala in Oracle -> succes raportat in VFP.
|
||||
|
||||
## De ce nu potriveste predicatul (cauza uzuala)
|
||||
|
||||
Santinela pusa doar pe coloana, nu si pe parametru:
|
||||
|
||||
AND NVL(A.CONT, 'XXXX') = V_CONT
|
||||
|
||||
VFP trimite sir gol pentru campul necompletat, iar in Oracle sirul gol **este NULL**; `'XXXX' = NULL`
|
||||
da UNKNOWN, deci zero randuri. Corect e pe amandoua:
|
||||
|
||||
AND NVL(A.CONT, 'XXXX') = NVL(V_CONT, 'XXXX')
|
||||
|
||||
Pe `ID_GESTIUNE` acelasi tipar merge, fiindca acolo VFP chiar trimite santinela `-1000`.
|
||||
|
||||
Cauza inrudita, acelasi simptom: un camp lipsa din lista de insert a cursorului, pe o coloana
|
||||
numerica **fara `NULL`** - ramane `0` tacit, nu NULL si nu eroare, si predicatul cade pe `0`.
|
||||
|
||||
## Ce se face, in ordinea asta
|
||||
|
||||
1. **Intai garda, apoi cauza.** Infasoara `SELECT ... INTO` in
|
||||
`BEGIN ... EXCEPTION WHEN NO_DATA_FOUND THEN RAISE_APPLICATION_ERROR(-20000, '... (FACT-0xx : ' || <cheia> || ')')`.
|
||||
Fara ea, orice reparatie de cauza ramane neverificabila: mecanismul care ascunde defectul e inca
|
||||
acolo. Codul `FACT-0xx` **se cauta liber in `USER_SOURCE`**, nu se presupune ca e liber.
|
||||
2. Abia apoi simetrizeaza predicatul.
|
||||
3. **Asertiune pe NUMARUL DE LINII** in testul de flux. Exact piesa care lipsea: identitatea
|
||||
documentului si legaturile lui se pastrau corect, deci toate asertiunile existente treceau.
|
||||
|
||||
## Cum se cauta preventiv
|
||||
|
||||
In `USER_SOURCE`: fiecare `SELECT ... INTO` fara `EXCEPTION` in ramura lui, si fiecare predicat de
|
||||
forma `NVL(<coloana>, <santinela>) = <parametru>`.
|
||||
|
||||
Precedent: `PACK_FACTURARE.adauga_articol_factura`, ramura `ntip = 4` (facturare din avize) - un
|
||||
document reemis cu 2 linii din 4, nedetectat de doua sweep-uri la rand. Reparat 04.09.2026 cu
|
||||
`FACT-030`.
|
||||
@@ -40,7 +40,13 @@ od -An -tx1 <fisier> | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq
|
||||
|
||||
La stricare censul CRESTE (un octet devine trei) - nu urmari doar scaderile. Cauta explicit
|
||||
secventa `EF BF BD`, nu tiparul generic `C3`/`C4`/`C5`/`C8` (acela apare si in UTF-8 legitim
|
||||
din cod).
|
||||
din cod). Decodat cp1250, `EF BF BD` apare ca "�" in caption.
|
||||
|
||||
Varianta veche, utila cand cauti pozitia exacta (linia) a unui octet suspect:
|
||||
|
||||
```bash
|
||||
perl -ne 'print "$.\n" if /[\x80-\xFF]/' <fisier>
|
||||
```
|
||||
|
||||
## Reparare
|
||||
|
||||
@@ -50,7 +56,12 @@ oarba cu 0xBA strica alte litere din alte pozitii. Ia octetul corect per pozitie
|
||||
PowerShell 5.1 (adauga BOM si re-encodeaza). Scrie inapoi ca bytes cp1250 explicit, apoi
|
||||
`txt2vcx.ps1` + fidelity check.
|
||||
|
||||
Cazul simplu (s-a pierdut doar 0xBA), inlocuire punctuala pe octet:
|
||||
Coruperea se repeta la FIECARE scriere, nu doar la prima: editeaza tot ce ai de editat, verifica
|
||||
byte-level, si repara o singura data DUPA ultima scriere - nu intre editari.
|
||||
|
||||
Cazul simplu (s-a pierdut doar un octet, cel original cunoscut, ex. 0xBA pentru s-cu-virgula),
|
||||
inlocuire punctuala pe secventa corupta - acelasi risc de coliziune poate afecta si alte fisiere
|
||||
cu acelasi octet, nu doar pozitia curenta:
|
||||
|
||||
```bash
|
||||
perl -e 'binmode(STDIN);binmode(STDOUT);local $/;$_=<STDIN>;s/\xEF\xBF\xBD/\xBA/g;print' < f > f.tmp
|
||||
|
||||
@@ -158,3 +158,11 @@ Cand un bug apare "de azi", compara cu clasa veche fara sa atingi SVN:
|
||||
Platit pe testarea VIES (23.08.2026): doua blocaje de 90s+; dupa stergerea celor doua fisiere,
|
||||
exact acelasi script a rulat in 1.19s. Completeaza punctul (1) din capcana precedenta: nu doar
|
||||
"exista `.ERR`?", ci si "e `.ERR`-ul de la rularea asta sau de la una anterioara?".
|
||||
- **`TYPE()` pe un obiect nu intoarce `'O'` pentru orice membru.** `.Objects` la un container
|
||||
(`Form`, `Container`, `Grid`) e *Objects Array*: `TYPE('loO.Objects')` da `'A'`, nu `'O'`. O
|
||||
garda `IF TYPE('loO.Objects') = 'O'` e deci mereu falsa, iar `AND`-ul scurtcircuiteaza testul
|
||||
corect de dupa ea - recursia pe arborele de controale nu porneste niciodata, **fara eroare si
|
||||
fara nimic in log**; singurul simptom e un dump care contine doar nivelul 1. Testeaza pe ce
|
||||
folosesti efectiv: `TYPE('loO.Objects.Count') = 'N'` e `'U'` daca lantul punctat nu exista,
|
||||
deci e si suficient, si independent de litera de tip. Aceeasi prudenta la `TYPE('loO.Value')`
|
||||
(tipul variaza cu continutul) si `TYPE('loO.Visible')`.
|
||||
|
||||
50
docs/instalare-ponytail.md
Normal file
50
docs/instalare-ponytail.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Instalare plugin Ponytail (Claude Code)
|
||||
|
||||
Plugin de nivel user (nu de proiect) care activeaza modul "lazy senior developer" descris in
|
||||
`~/.claude/CLAUDE.md`. Se instaleaza o singura data per calculator, in contul Windows al
|
||||
utilizatorului.
|
||||
|
||||
## Pasi
|
||||
|
||||
Din orice sesiune `claude` (sau `claude -p` cu `--dangerously-skip-permissions` daca ruleaza
|
||||
neatended):
|
||||
|
||||
```
|
||||
claude plugin marketplace add DietrichGebert/ponytail
|
||||
claude plugin install ponytail@ponytail
|
||||
```
|
||||
|
||||
Reporneste sesiunea Claude Code dupa instalare (plugin-urile se incarca la pornire).
|
||||
|
||||
## Verificare
|
||||
|
||||
```
|
||||
claude plugin list
|
||||
```
|
||||
|
||||
Trebuie sa apara `ponytail@ponytail` ca instalat si activ. Sau verifica direct in
|
||||
`~/.claude/settings.json`:
|
||||
|
||||
```json
|
||||
"enabledPlugins": {
|
||||
"ponytail@ponytail": true
|
||||
},
|
||||
"extraKnownMarketplaces": {
|
||||
"ponytail": {
|
||||
"source": { "source": "github", "repo": "DietrichGebert/ponytail" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Nivel implicit
|
||||
|
||||
Nivelul (`lite|full|ultra`) e setat per sesiune cu `/ponytail <nivel>` sau ramane pe default-ul
|
||||
plugin-ului. Regulile de scara YAGNI/reuse-first pentru proiectele ROA sunt in
|
||||
`reguli_lucru.md`, punctul 3 ("Scara ponytail") — se aplica dupa instalare, nu fac parte din
|
||||
instalarea in sine.
|
||||
|
||||
## Dezinstalare
|
||||
|
||||
```
|
||||
claude plugin uninstall ponytail@ponytail
|
||||
```
|
||||
246
docs/prompt_recreare_statusline.md
Normal file
246
docs/prompt_recreare_statusline.md
Normal file
@@ -0,0 +1,246 @@
|
||||
# Prompt pentru alta sesiune: recreeaza statusline-ul Claude Code
|
||||
|
||||
Copiaza tot ce urmeaza si trimite-l ca prompt intr-o sesiune Claude Code noua
|
||||
(pe alta masina/user), ca sa recreeze exact statusline-ul curent (Windows / Git Bash).
|
||||
|
||||
---
|
||||
|
||||
Vreau sa configurezi un statusline custom pentru Claude Code, pe Windows cu Git Bash.
|
||||
|
||||
1. Verifica ca exista `jq.exe` in `~/.claude/bin/jq.exe`. Daca nu exista, descarca
|
||||
binarul oficial jq pentru Windows (jq-win64.exe de pe github.com/jqlang/jq/releases)
|
||||
si salveaza-l acolo ca `jq.exe`.
|
||||
|
||||
2. Creeaza fisierul `~/.claude/statusline.sh` (bash, LF, executabil) cu continutul de mai jos.
|
||||
|
||||
3. In `~/.claude/settings.json`, adauga/actualizeaza cheia de nivel radacina:
|
||||
```json
|
||||
"statusLine": {
|
||||
"type": "command",
|
||||
"command": "C:/Users/<USER>/.claude/statusline.sh"
|
||||
}
|
||||
```
|
||||
(inlocuieste `<USER>` cu userul curent; foloseste slash-uri, nu backslash).
|
||||
|
||||
Ce face scriptul:
|
||||
- Linia 1: model | ctx folosit/total si % din fereastra | proiect (branch git, cu `*` daca e dirty)
|
||||
- Linia 2: trei bare de puncte (10 puncte fiecare) pentru consum curent (5h), saptamanal (7 zile)
|
||||
si sonnet (7 zile) — procent + timp pana la reset, in format `●●●○○○○○○○ 30% ↺ 2hr 15min`
|
||||
- Cele trei procente vin din `/api/oauth/usage` (acelasi endpoint ca ecranul `/usage`),
|
||||
cu cache de 10 minute in `~/.claude/.statusline-usage.json` si backoff la 429/eroare
|
||||
(20 min, respectiv 5 min), ca sa nu loveasca rate-limit-ul la fiecare prompt.
|
||||
- Pana la primul fetch reusit, current/weekly cad back pe `rate_limits` din JSON-ul primit pe stdin.
|
||||
- Token-ul OAuth se ia din `~/.claude/.credentials.json` (`claudeAiOauth.accessToken`).
|
||||
- La inceput reface PATH-ul (`$HOME/.claude/bin:/usr/bin:/bin:$PATH`), pentru ca Claude Code
|
||||
lanseaza scriptul ca shell non-login/non-interactiv, deci profilul Git Bash nu se incarca
|
||||
si PATH-ul nu are coreutils.
|
||||
|
||||
Continutul complet al `~/.claude/statusline.sh`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Claude Code Statusline (Windows / Git Bash)
|
||||
# Line 1: Model | ctx 33K/1M 3% | project (branch*)
|
||||
# Line 2: current <bar> 24% ↺ 3hr │ weekly <bar> 4% ↺ Thu 7pm │ sonnet <bar> 2% ↺ Thu 7pm
|
||||
#
|
||||
# All three usage figures come from /api/oauth/usage -- the same source as the
|
||||
# `/usage` screen -- so the numbers match it exactly. That endpoint is rate-
|
||||
# limited, so the result is cached for 10 min; on failure the last good values
|
||||
# are kept. Until the first successful fetch, current/weekly fall back to the
|
||||
# `rate_limits` object on stdin (slightly different snapshot, but never blank).
|
||||
|
||||
set -o pipefail
|
||||
|
||||
# Claude Code spawns this as a non-login, non-interactive shell, so Git Bash's
|
||||
# profile is never sourced and PATH has no coreutils. Restore them explicitly,
|
||||
# plus the bundled jq.exe in ~/.claude/bin.
|
||||
export PATH="$HOME/.claude/bin:/usr/bin:/bin:$PATH"
|
||||
|
||||
input=$(cat)
|
||||
|
||||
# Validate JSON
|
||||
if ! echo "$input" | jq -e . >/dev/null 2>&1; then
|
||||
printf '\033[90mLoading...\033[0m'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- Context / project (line 1) ---
|
||||
model=$(echo "$input" | jq -r '.model.display_name // "?"')
|
||||
workdir=$(echo "$input" | jq -r '.workspace.current_dir // ""')
|
||||
project=$(basename "$workdir" 2>/dev/null) || project="?"
|
||||
|
||||
ctx_pct=$(echo "$input" | jq -r '(.context_window.used_percentage // 0) | floor')
|
||||
[[ "$ctx_pct" =~ ^[0-9]+$ ]] || ctx_pct=0
|
||||
|
||||
ctx_size=$(echo "$input" | jq -r '.context_window.context_window_size // 0')
|
||||
ctx_input=$(echo "$input" | jq -r '.context_window.current_usage.input_tokens // 0')
|
||||
ctx_output=$(echo "$input" | jq -r '.context_window.current_usage.output_tokens // 0')
|
||||
ctx_cache_create=$(echo "$input" | jq -r '.context_window.current_usage.cache_creation_input_tokens // 0')
|
||||
ctx_cache_read=$(echo "$input" | jq -r '.context_window.current_usage.cache_read_input_tokens // 0')
|
||||
ctx_used=$(( ctx_input + ctx_output + ctx_cache_create + ctx_cache_read ))
|
||||
|
||||
fmt_tokens() {
|
||||
local n=$1
|
||||
if [ "$n" -ge 1000000 ]; then printf "%dM" $(( n / 1000000 ))
|
||||
elif [ "$n" -ge 1000 ]; then printf "%dK" $(( n / 1000 ))
|
||||
else printf "%d" "$n"; fi
|
||||
}
|
||||
ctx_used_fmt=$(fmt_tokens "$ctx_used")
|
||||
ctx_size_fmt=$(fmt_tokens "$ctx_size")
|
||||
|
||||
# Git branch with dirty marker
|
||||
git_branch=""
|
||||
if [ -n "$workdir" ] && [ -d "$workdir" ]; then
|
||||
git_branch=$(cd "$workdir" 2>/dev/null && git -c gc.auto=0 rev-parse --abbrev-ref HEAD 2>/dev/null) || git_branch=""
|
||||
if [ -n "$git_branch" ]; then
|
||||
git_dirty=$(cd "$workdir" 2>/dev/null && git -c gc.auto=0 status --porcelain 2>/dev/null | head -1)
|
||||
[ -n "$git_dirty" ] && git_branch="${git_branch}*"
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Usage: all three figures from /api/oauth/usage, cached ---
|
||||
USAGE_CACHE="$HOME/.claude/.statusline-usage.json"
|
||||
USAGE_REFRESH=600 # refresh at most every 10 min
|
||||
USAGE_BACKOFF_429=1200 # after a rate-limit, wait 20 min before retrying
|
||||
USAGE_BACKOFF_ERR=300 # after any other error, wait 5 min
|
||||
|
||||
now=$(date +%s)
|
||||
c5p=""; c5r=""; c7p=""; c7r=""; csp=""; csr=""; fetched=0; retry=0
|
||||
|
||||
read_usage_cache() {
|
||||
[ -f "$USAGE_CACHE" ] || return
|
||||
c5p=$(jq -r '.five_hour_pct // ""' "$USAGE_CACHE" 2>/dev/null)
|
||||
c5r=$(jq -r '.five_hour_reset // ""' "$USAGE_CACHE" 2>/dev/null)
|
||||
c7p=$(jq -r '.seven_day_pct // ""' "$USAGE_CACHE" 2>/dev/null)
|
||||
c7r=$(jq -r '.seven_day_reset // ""' "$USAGE_CACHE" 2>/dev/null)
|
||||
csp=$(jq -r '.sonnet_pct // ""' "$USAGE_CACHE" 2>/dev/null)
|
||||
csr=$(jq -r '.sonnet_reset // ""' "$USAGE_CACHE" 2>/dev/null)
|
||||
fetched=$(jq -r '(.fetched_at // 0) | floor' "$USAGE_CACHE" 2>/dev/null || echo 0)
|
||||
retry=$(jq -r '(.retry_until // 0) | floor' "$USAGE_CACHE" 2>/dev/null || echo 0)
|
||||
}
|
||||
read_usage_cache
|
||||
[[ "$fetched" =~ ^[0-9]+$ ]] || fetched=0
|
||||
[[ "$retry" =~ ^[0-9]+$ ]] || retry=0
|
||||
|
||||
write_usage_cache() { # 5p 5r 7p 7r sp sr fetched_at retry_until
|
||||
printf '{"five_hour_pct":"%s","five_hour_reset":"%s","seven_day_pct":"%s","seven_day_reset":"%s","sonnet_pct":"%s","sonnet_reset":"%s","fetched_at":%s,"retry_until":%s}\n' \
|
||||
"$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" > "$USAGE_CACHE"
|
||||
}
|
||||
|
||||
refresh_usage() {
|
||||
local creds="$HOME/.claude/.credentials.json" token tmp http
|
||||
[ -f "$creds" ] || return
|
||||
token=$(jq -r '.claudeAiOauth.accessToken // empty' "$creds" 2>/dev/null)
|
||||
[ -n "$token" ] || return
|
||||
tmp="$HOME/.claude/.statusline-usage.tmp.$$"
|
||||
http=$(curl -s -o "$tmp" -w '%{http_code}' --max-time 3 \
|
||||
-H "Authorization: Bearer $token" \
|
||||
-H "anthropic-beta: oauth-2025-04-20" \
|
||||
-H "Content-Type: application/json" \
|
||||
"https://api.anthropic.com/api/oauth/usage" 2>/dev/null)
|
||||
if [ "$http" = "200" ]; then
|
||||
local p5 r5 p7 r7 ps rs
|
||||
p5=$(jq -r 'if .five_hour.utilization!=null then (.five_hour.utilization|floor) else "" end' "$tmp" 2>/dev/null)
|
||||
r5=$(jq -r '.five_hour.resets_at // ""' "$tmp" 2>/dev/null)
|
||||
p7=$(jq -r 'if .seven_day.utilization!=null then (.seven_day.utilization|floor) else "" end' "$tmp" 2>/dev/null)
|
||||
r7=$(jq -r '.seven_day.resets_at // ""' "$tmp" 2>/dev/null)
|
||||
ps=$(jq -r 'if .seven_day_sonnet.utilization!=null then (.seven_day_sonnet.utilization|floor) else "" end' "$tmp" 2>/dev/null)
|
||||
rs=$(jq -r '.seven_day_sonnet.resets_at // ""' "$tmp" 2>/dev/null)
|
||||
write_usage_cache "$p5" "$r5" "$p7" "$r7" "$ps" "$rs" "$now" 0
|
||||
elif [ "$http" = "429" ]; then
|
||||
write_usage_cache "$c5p" "$c5r" "$c7p" "$c7r" "$csp" "$csr" "$fetched" "$(( now + USAGE_BACKOFF_429 ))"
|
||||
else
|
||||
write_usage_cache "$c5p" "$c5r" "$c7p" "$c7r" "$csp" "$csr" "$fetched" "$(( now + USAGE_BACKOFF_ERR ))"
|
||||
fi
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
if [ "$(( now - fetched ))" -gt "$USAGE_REFRESH" ] && [ "$now" -gt "$retry" ]; then
|
||||
refresh_usage
|
||||
read_usage_cache
|
||||
fi
|
||||
|
||||
# current / weekly: use API cache; fall back to stdin rate_limits if not yet fetched
|
||||
if [ -n "$c5p" ]; then
|
||||
five_hr_pct=$c5p; five_hr_reset=$c5r
|
||||
else
|
||||
five_hr_pct=$(echo "$input" | jq -r '(.rate_limits.five_hour.used_percentage // 0) | floor')
|
||||
five_hr_reset=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at // ""')
|
||||
fi
|
||||
if [ -n "$c7p" ]; then
|
||||
weekly_pct=$c7p; weekly_reset=$c7r
|
||||
else
|
||||
weekly_pct=$(echo "$input" | jq -r '(.rate_limits.seven_day.used_percentage // 0) | floor')
|
||||
weekly_reset=$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at // ""')
|
||||
fi
|
||||
# sonnet: only available from the API
|
||||
sonnet_pct=${csp:-0}; sonnet_reset=$csr
|
||||
|
||||
[[ "$five_hr_pct" =~ ^[0-9]+$ ]] || five_hr_pct=0
|
||||
[[ "$weekly_pct" =~ ^[0-9]+$ ]] || weekly_pct=0
|
||||
[[ "$sonnet_pct" =~ ^[0-9]+$ ]] || sonnet_pct=0
|
||||
|
||||
# --- reset-time formatting (accepts epoch seconds or ISO string) ---
|
||||
to_epoch() {
|
||||
local v="${1%%.*}"
|
||||
if [ -z "$v" ] || [ "$v" = "null" ]; then return 1; fi
|
||||
if [[ "$v" =~ ^[0-9]+$ ]]; then printf '%s' "$v"
|
||||
else date -d "$1" +%s 2>/dev/null || return 1; fi
|
||||
}
|
||||
|
||||
fmt_reset() {
|
||||
# No TZ= : Git Bash's date has no zoneinfo DB, but with TZ unset it uses the
|
||||
# Windows system timezone correctly. Setting TZ=Europe/... falls back to UTC.
|
||||
local e
|
||||
e=$(to_epoch "$1") || { printf '%s' "--"; return; }
|
||||
date -d "@$e" "+%a %-I:%M%P" 2>/dev/null || printf '%s' "--"
|
||||
}
|
||||
|
||||
fmt_remaining() {
|
||||
local e now_ts rem rh rm rd
|
||||
e=$(to_epoch "$1") || { printf '%s' "--"; return; }
|
||||
now_ts=$(date +%s)
|
||||
if [ "$e" -gt "$now_ts" ]; then
|
||||
rem=$(( e - now_ts )); rh=$(( rem / 3600 )); rm=$(( (rem % 3600) / 60 ))
|
||||
if [ "$rh" -gt 24 ]; then
|
||||
rd=$(( rh / 24 )); rh=$(( rh % 24 )); printf "%dd %dh" "$rd" "$rh"
|
||||
elif [ "$rh" -gt 0 ]; then printf "%dhr %dmin" "$rh" "$rm"
|
||||
else printf "%dmin" "$rm"; fi
|
||||
else printf "resetting"; fi
|
||||
}
|
||||
|
||||
five_hr_remain=$(fmt_remaining "$five_hr_reset")
|
||||
weekly_reset_str=$(fmt_reset "$weekly_reset")
|
||||
sonnet_reset_str=$(fmt_reset "$sonnet_reset")
|
||||
|
||||
# --- dot bar ---
|
||||
DOT_TOTAL=10
|
||||
make_dots() {
|
||||
local pct=$1 filled i dots=""
|
||||
filled=$(( pct * DOT_TOTAL / 100 ))
|
||||
[ "$filled" -gt "$DOT_TOTAL" ] && filled=$DOT_TOTAL
|
||||
[ "$filled" -lt 0 ] && filled=0
|
||||
for (( i=0; i<DOT_TOTAL; i++ )); do
|
||||
if [ "$i" -lt "$filled" ]; then dots="${dots}●"; else dots="${dots}○"; fi
|
||||
done
|
||||
printf "%s" "$dots"
|
||||
}
|
||||
|
||||
# --- build & output ---
|
||||
if [ -n "$git_branch" ]; then
|
||||
proj_display="${project} (${git_branch})"
|
||||
else
|
||||
proj_display="${project}"
|
||||
fi
|
||||
line1=$(printf "%s │ ctx %s/%s %d%% │ %s" "$model" "$ctx_used_fmt" "$ctx_size_fmt" "$ctx_pct" "$proj_display")
|
||||
|
||||
line2=$(printf "current %s %d%% ↺ %s │ weekly %s %d%% ↺ %s │ sonnet %s %d%% ↺ %s" \
|
||||
"$(make_dots "$five_hr_pct")" "$five_hr_pct" "$five_hr_remain" \
|
||||
"$(make_dots "$weekly_pct")" "$weekly_pct" "$weekly_reset_str" \
|
||||
"$(make_dots "$sonnet_pct")" "$sonnet_pct" "$sonnet_reset_str")
|
||||
|
||||
printf "%s\n%s" "$line1" "$line2"
|
||||
```
|
||||
|
||||
Dupa ce salvezi fisierul si actualizezi `settings.json`, deschide o sesiune noua Claude
|
||||
Code (sau `/statusline` refresh) ca sa vezi statusline-ul aplicat.
|
||||
@@ -50,8 +50,34 @@
|
||||
`clase\anaf_efactura.vcx`. Motivul e de intretinere: un `.prg` se editeaza direct si diff-ul lui
|
||||
se citeste in git, pe cand codul pus ca metoda in binar trece prin FoxBin2Prg si write-back si
|
||||
se urmareste greu.
|
||||
**Scara ponytail** (plugin activ implicit pe `full`, injectat si in subagenti; `ultra` nu se
|
||||
foloseste pe cod legacy partajat): opreste-te la prima treapta care tine - 1) trebuie sa existe?
|
||||
2) exista deja (`inventar-comun.md`, `COMUN\programe`, `COMUN\clase`) -> refolosesti; 3) o
|
||||
functie VFP nativa o face; 4) se rezolva pe Oracle (view, constrangere, pachet) in loc de cod
|
||||
client; 5) o linie; 6) abia apoi minimul care merge. Scurteaza SOLUTIA, nu cititul - intai
|
||||
urmaresti fluxul real atins. Nu se simplifica niciodata: garzile pe NULL, validarile, tratarea
|
||||
erorilor, drepturile de acces, ce s-a cerut explicit.
|
||||
Abateri obligatorii fata de plugin: (a) **fara comentarii `ponytail:`** in cod (regula 2) -
|
||||
scurtatura deliberata si limita ei se noteaza in `docs\progres.md`, deci `/ponytail-debt` nu
|
||||
are ce culege aici; (b) proba unei logici noi e un script headless (regulile 4 si 8), nu
|
||||
`test_*.py`; (c) handoff-urile, rapoartele din `docs\` si patch-urile sunt output cerut
|
||||
explicit - regula "cod intai, maxim trei randuri" nu li se aplica; (d) `/ponytail-review` pe
|
||||
diff-ul rundei inainte de commit e util, dar `delete:`/`yagni:` sunt IPOTEZE, nu constatari: in
|
||||
`COMUN` apelantii sunt in toate produsele, deci cauti in tot `D:\ROA` inainte sa stergi, iar o
|
||||
garda fara caz in datele de test nu e garda moarta (regula 6); `/ponytail-audit` pe tot
|
||||
arborele nu se ruleaza aici.
|
||||
4. Testare headless (fara IDE): `vfp9.exe -A -T "<script.prg>" <param>` din PowerShell.
|
||||
Mediu, sabloane, capcane, depanare: `depanare_testare_vfp.md`.
|
||||
Rularile intermediare acopera doar familiile de teste atinse de modificarea curenta; suita
|
||||
completa, inclusiv testele de garda pe zonele vecine, se ruleaza doar la rularea finala —
|
||||
garzile exista fiindca schimbarile cad de regula in cod partajat (`COMUN`), vizibil in toate
|
||||
produsele, dar costul lor nu se plateste la fiecare rulare intermediara. Ideal, doar testele
|
||||
atinse direct (de regula 3-10), nu toata familia.
|
||||
Un test normal dureaza 1-5s — ce umfla o rulare nu e testarea, ci asteptarea unui test atarnat.
|
||||
La rulari intermediare: timeout **90s**/test (ce trece de atat e atarnat, nu lent) si pauza
|
||||
**0,5s** intre teste, nu implicitul de 12 minute / 3s, rezervat rularii finale unde chiar
|
||||
conteaza sa distingi "atarnat" de "lent". Tinta: o rulare intermediara sta in secunde-minute,
|
||||
nu ore — daca depaseste, lista e prea larga sau timeout-ul prea mare.
|
||||
5. Editare .vcx/.scx pe text (cache, cp1250 byte-safe, fidelity-check): `flux-editare-vfp-text.md`.
|
||||
Cautare in binare: `cautare_vcx_vct.md`. Versiunile `.??2` sunt instantanee, pot fi mai vechi
|
||||
decat binarul — verifica mtime inainte de concluzii; continutul real e in `.PJX`.
|
||||
@@ -61,12 +87,14 @@
|
||||
tokens/subagent), nu unul singur cu context acumulat; handoff compact pe disc. Verificarea a
|
||||
ce se intoarce si modelul de lucru (backlog de story-uri mici): `orchestrare-subagenti.md`.
|
||||
7. Conventii obligatorii, de citit cand atingi zona respectiva:
|
||||
- editezi `.vc2`/`.sc2` sau `.prg` cu diacritice (ex. `programe\ocautare.prg`) -> fisierele
|
||||
sunt **cp1250** desi antetul FoxBin2Prg declara `CPID="1252"`; Edit/Write corup TOT fisierul
|
||||
(nu doar linia atinsa) la fiecare scriere - scrie continut nou strict ASCII. Cens obligatoriu
|
||||
- editezi `.vc2`/`.sc2` sau `.prg` cu diacritice (ex. `programe\ocautare.prg`, unde `s`-urile cu
|
||||
virgula din `masina`/`si contul`/`transa` sunt octetul `0xBA`) -> fisierele sunt **cp1250**
|
||||
desi antetul FoxBin2Prg declara `CPID="1252"`; Edit/Write corup TOT fisierul (nu doar linia
|
||||
atinsa), ireversibil, la fiecare scriere - scrie continut nou strict ASCII. Cens obligatoriu
|
||||
**inainte SI dupa** fiecare editare (la stricare CRESTE, nu scade):
|
||||
`od -An -tx1 <fisier> | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c`. Tabel
|
||||
de octeti si reparare -> `conventie_encoding_cp1252.md`;
|
||||
`od -An -tx1 <fisier> | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c`. Tabelul
|
||||
complet de octeti, sensul censului la stricare si procedura de recuperare din git/svn ->
|
||||
`conventie_encoding_cp1252.md`;
|
||||
- adaugi o PROPRIETATE sau o METODA noua intr-o clasa `.vc2`/`.sc2` -> `flux-editare-vfp-text.md`,
|
||||
sectiunea "Membri noi de clasa": fara intrarea `*p:`/`*m:` in `*<DefinedPropArrayMethod>`
|
||||
membrul trece fidelity-check-ul, dar VFP nu-l vede si prima salvare din IDE il sterge tacut;
|
||||
@@ -80,6 +108,8 @@
|
||||
- te conectezi la Oracle pe dev/test, alegi schema sau rulezi un script de pachet ->
|
||||
`conventie_mediu_oracle.md`;
|
||||
- garzi pe valori NULL din Oracle -> `conventie_null_vfp.md`;
|
||||
- procedura PL/SQL cu `SELECT ... INTO` chemata din VFP (linii pierdute tacut) ->
|
||||
`capcana_sqlexec_no_data_found.md`;
|
||||
- export date din Oracle -> `oracle_export.md`;
|
||||
- actualizarea ROA nu se finalizeaza (job update, PACK_UPDATE) -> `depanare-pack-update.md`;
|
||||
- modifici schema Oracle (tabele/view-uri/pachete) -> `scripturi-migrare-db.md`.
|
||||
|
||||
@@ -112,6 +112,28 @@ fluxuri valorice.
|
||||
in urma. Inainte de a te baza pe o linie din el pentru o modificare, confirm-o pe cod
|
||||
(`initializeaza_date_factura`, `CASE`-urile din view-uri) sau pe `XSETS`.
|
||||
|
||||
## Domeniul regenerabil (planul #13)
|
||||
|
||||
Planul #13 introduce editarea articolelor unui document deja emis prin stergere + reemitere
|
||||
(acelasi numar de document, rand nou in `VANZARI`). Domeniul acestui mecanism nu acopera tot
|
||||
`VANZARI.TIP`:
|
||||
|
||||
- **In afara domeniului, prin decizie explicita a lui Marius** (confirmat de inventarul de FK din
|
||||
S11): documentele legate de `REST_NOTE_PLATA` (modul restaurant, `TIP` 46) si de
|
||||
`IPS_VOYAGES_VANZARI` (facturarea voiajelor din ROAACNPRO, `TIP` 51). Pentru ele ramane calea
|
||||
veche de editare pe loc (#6); intrarea in formularul nou le refuza explicit, nu doar le ignora.
|
||||
- **Declarate explicit neacoperite** (recomandare "nu acum"): tipurile **48/49** (custodie) -
|
||||
incarcarea unui document existent in formularul nou nu e implementata pentru ele. Tinta unica
|
||||
pentru editare ramane `frm_facturare_articole2` (formularul nou) - `frm_facturare_articole`
|
||||
(formularul vechi) nu mai primeste cod nou.
|
||||
- **Datorie deschisa, nu excludere**: documentele CONTRACT cu linii de rata
|
||||
(`VANZARI_DETALII.ID_RATA <> 0`) esueaza la reemitere cu eroarea Oracle `Too many columns.` -
|
||||
19 din cele 21 de documente CONTRACT vii sunt in acest perimetru. Cauza-radacina **nu e
|
||||
dovedita**; nu exista azi o reparatie.
|
||||
|
||||
Restul tipurilor din tabelele de mai sus sunt in domeniul regenerabil, verificat pe cele patru
|
||||
familii de scriere (AVIZ, COMANDA, CONTRACT, ELSE).
|
||||
|
||||
## Legaturi
|
||||
|
||||
- `scripturi-migrare-db.md` — sursa de referinta pentru DDL e `MARIUSM_AUTO`, nu o schema de client.
|
||||
|
||||
@@ -24,7 +24,7 @@ DONE 9. ROAGEST - MODIFICARE REGISTRU JURNAL - SA SE POATA MODIFICA SI "NNIR" in
|
||||
|
||||
10. ROAFACTURARE - Integrare pagina contracte si rapoarte contracte in ROAFACTURARE, similar COMENZI in ROAFACTURARE - facturare pe baza de comenzi/contracte. trebuie comasate si drepturile pe obiectele din roacontracte cu obiectele noi din ROAFACTURARE.
|
||||
|
||||
11. ROAFACTURARE - Integrare politici de preturi in ROAFACTURARE - sunt numai editari de liste de preturi, note contabile, nomenclator articole, drepturi pe liste de preturi, care toate se folosesc numai in programul ROAFACTURARE
|
||||
11. ROAFACTURARE - Integrare politici de preturi in ROAFACTURARE - sunt numai editari de liste de preturi, note contabile, nomenclator articole, drepturi pe liste de preturi, care toate se folosesc numai in programul ROAFACTURARE.
|
||||
|
||||
12. ROAFACTURARE - sa pot sa folosesc direct nomenclatorul de articole pe post de lista de preturi, sa nu mai definesc liste de preturi, note contabile asociate. Acum am un echivalent (lista de articole din stoc ca o lista de preturi virtuala)
|
||||
|
||||
@@ -90,3 +90,14 @@ DONE 21. ROACONT - in formularul de verificare coduri fiscale, ar trebui sa fie
|
||||
39. ROA - asistent de suport pe documentatia proprie; butonul de chat exista deja in mesajele de eroare, ii lipseste continutul (manual, versiuni, dictionar de erori). (rec_directie_roacont_2026_09.md, 3.6)
|
||||
|
||||
40. ROACONT - e-Transport: azi nu exista nimic, concurenta are modul dedicat. (rec_directie_roacont_2026_09.md, 3.7)
|
||||
|
||||
41. ROACONT - daca se permite modificarea manuala a sumelor de la TVA, nu se poate si o atentionare daca TVA este altul decat procentul din explicatia de TVA selectata?
|
||||
|
||||
42. ROAFACTURARE - configurarea initiala pentru a putea factura un articol - este foarte complexa si vreau mai fluid, poate si cu un wizzard
|
||||
- definire grup TOTAL in ROADEF si asociere utilizatori in grupul TOTAL
|
||||
- creare articol in ROAPRETURI
|
||||
- creare nota contabila vanzare
|
||||
- creare politica preturi si introducere articol
|
||||
- definire serii numere facturi
|
||||
- completare optiuni document factura, aviz, documente incasare, bon fiscal, bon pos
|
||||
Poate un wizzard
|
||||
|
||||
Reference in New Issue
Block a user