Wire outbound Invoice/Document sync after confirmed ops, store sync status with timeout lock, and keep SQL credentials out of frontend responses.
Co-authored-by: Cursor <cursoragent@cursor.com>
Admin charge can now wipe the exact remaining balance when a count product has a leftover decimal amount.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add admin decision to write app wallet onto Tahesab even when zero, always await colleague callback regardless of the wait switch, and SMS admins on colleague reject.
Co-authored-by: Cursor <cursoragent@cursor.com>
The list stream must tell clients whether each product is open so the device clock cannot reopen a closed shop.
Co-authored-by: Cursor <cursoragent@cursor.com>
Clear tahesab_id on locally successful rows so they re-enter the send queue without touching panel customer codes.
Co-authored-by: Cursor <cursoragent@cursor.com>
After pending docs finish, the same pump writes customers without a code into Tahesab. Inbound import is server-side; the admin only polls status.
Co-authored-by: Cursor <cursoragent@cursor.com>
File cache cannot use Cache::lock, so docs for customers without a code always failed. Register first, put the customer name on the sanad, and surface the real error.
Co-authored-by: Cursor <cursoragent@cursor.com>
Pending list was empty because a missing tahesab table hid unsynced orders and charges. Create the table when needed and keep customer on each row.
Co-authored-by: Cursor <cursoragent@cursor.com>
Gholaktala has no local tahesab table; count queries now return empty pending stats instead of QueryException.
Co-authored-by: Cursor <cursoragent@cursor.com>
Send leftover orders and charges one-by-one with a gap so Tahesab is not rate-limited, skip already-synced rows, and expose start/stop plus progress on existing status APIs.
Co-authored-by: Cursor <cursoragent@cursor.com>
The list edit dumped the whole table row into update(); whitelist form and accounting fields, and skip hashing an empty password.
Co-authored-by: Cursor <cursoragent@cursor.com>
Empty SuperAdmin chargeInfo was wiping sms_charge_* on header refresh.
Seed those keys only when empty, and move referral_bonus_amount to can_edit=1.
Co-authored-by: Cursor <cursoragent@cursor.com>
Zarin pooli returns HTTP 400 when fi is empty; a quote within 25% of market is required, which still posts as خرید فی.
Co-authored-by: Cursor <cursoragent@cursor.com>
Wallet docs were sending mazaneh as fi so Zarin turned cash deposits into خرید فی rows; customer buy/sell used the inverted korf mapping.
Co-authored-by: Cursor <cursoragent@cursor.com>
Route online wallet deposits to Tahesab/Zarin wallet() instead of leaving
staff to post gold buy docs; keep «شارژ حساب» in accounting notes.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add inbound mande sync on customer import plus per-customer and bulk wallet-sync endpoints so previously linked accounts can catch up.
Co-authored-by: Cursor <cursoragent@cursor.com>
Port tables, APIs, and overdue cron from goldali, default the flag off, and keep customer routes behind auth.
Co-authored-by: Cursor <cursoragent@cursor.com>
Stale Redis overlay and SMS-origin-first fetch kept feature flags like customer_special_pricing false after SuperAdmin turned them on. Always fetch live and try adm.montzar.ir first.
Co-authored-by: Cursor <cursoragent@cursor.com>
Reuse an existing Zarin hesab instead of a second addhesab, and stop rial-locked orders from treating mesghal as per-gram.
Co-authored-by: Cursor <cursoragent@cursor.com>
Admin banner uploads were lost on refresh when an older const row or empty value column was served instead of the saved JSON.
Co-authored-by: Cursor <cursoragent@cursor.com>
Post Montzar-covered buy/sell to Zarin/Tahesab/Pargar using montzar_account_* settings, and harden public storage URL/MIME handling for uploads.
Co-authored-by: Cursor <cursoragent@cursor.com>
Menu gates like enable_product_funds were missing from the public API, so the user app could not hide disabled features.
Co-authored-by: Cursor <cursoragent@cursor.com>