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>
Run one-time overflow cleanup on migrate and keep mande/document success
rows capped at 2000 with an AFTER INSERT trigger, without cron or manual SQL.
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>
Split frontends like my.goldarvin.ir were waiting on 404 retries for the API hostname, which made get_settings take ~16s.
Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the newest 2000 success rows per inbound type so dumps stop growing from Pargar webhooks, and store compact document payloads instead of full JSON.
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>
Keep cover orders pending until colleague sts 2/4/6 via callback or 35s poll. Nightly prices:prune also drops old log tables.
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>
Create the Elif order first (pending colleague), then submit to Liman so failed quote or wallet attempts stay visible instead of leaving orphan provider trades.
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>
Map Shahkar mismatch, token, unreachable, and duplicate cases to clear Persian messages instead of a generic wait-for-admin toast.
Co-authored-by: Cursor <cursoragent@cursor.com>
Gold gram prices now exceed the old DECIMAL/INT range and MySQL 1264 aborted buys; store money fields as DECIMAL(20,4) and hide the raw SQL error from the app.
Co-authored-by: Cursor <cursoragent@cursor.com>
When the partner rejects with a mazaneh-changed error, pull the live quote and submit once more so the customer buy can succeed without a page refresh.
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>
A stray montzar tick landed in the prices table, which stores no source, so
the database_last fallback served a ~168M quote on a shop whose Zaarbox board
was at ~217M. Last price and today's high/low now come from price_sync_logs
filtered by price_provider, the database fallback no longer counts as today's
price, and daily extremes reset when the provider changes.
Co-authored-by: Cursor <cursoragent@cursor.com>
Profile and bank-card save paths now succeed with clear pending-admin copy instead of a validation error when automatic Jibit checks are disabled.
Co-authored-by: Cursor <cursoragent@cursor.com>
Preview and conflict paths now include recent wallet and Tahesab documents, and applied adjustments use a visible type/title/note so customers can see the sync document.
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>
Expand www/admin domain aliases when resolving program-settings, and save owned keys to local settings after a successful refresh so menu flags like customer_special_pricing stay applied.
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>
Find orphan buy transactions or accept --gold/--transaction so wallet gold can still be stripped and cash recharged.
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>
Store SSE payloads were Eloquent models, so listIdentity skipped them and file_id changes never republished; encode to plain arrays before hash/publish.
Co-authored-by: Cursor <cursoragent@cursor.com>
Image uploads were ignored by the live list hash, so the stream kept republishing a stale product payload and the theme reverted to the old photo.
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>
Stale prices rows were rejecting a valid ~220M partner quote against an old ~168M reference and locking the app on database_last.
Co-authored-by: Cursor <cursoragent@cursor.com>
Stored DB prices were treated as live quotes, and SuperAdmin overlay overwrote tenant keys like trading hours. Keep overlay to the 14 access flags and hide fallback prices when the panel says so.
Co-authored-by: Cursor <cursoragent@cursor.com>
Recompute home price display on save, broadcast settings over SSE, and keep last-price status in sync without a user refresh.
Co-authored-by: Cursor <cursoragent@cursor.com>
Schedule runs that hit cooldown or max-send limits now write a skipped row to automation_sends so admins can see why no SMS was sent.
Co-authored-by: Cursor <cursoragent@cursor.com>
Install per-module schedule:run cron from artisan, store sms/in_app send minutes, and match scheduled triggers at exact HH:mm Tehran time.
Co-authored-by: Cursor <cursoragent@cursor.com>
Resolve display name from name_fa/name/name_en, skip duplicate lines, and support %نام_اپ placeholder in templates.
Co-authored-by: Cursor <cursoragent@cursor.com>
The name placeholder regex was matching the prefix of %نام_کوچک first, leaving _کوچک in the rendered message.
Co-authored-by: Cursor <cursoragent@cursor.com>
Enable immediate automation test runs without waiting for the scheduled hour, expose send history for debugging, and return all SuperAdmin overlay keys on refresh instead of only enable_automation.
Co-authored-by: Cursor <cursoragent@cursor.com>
Use trading_hours_by_day for close_price gates, prefer public SuperAdmin fetch, and add refresh endpoint/command so stale last-good cache no longer keeps switches like enable_automation off.
Co-authored-by: Cursor <cursoragent@cursor.com>
Ignore limangold/payping seed URLs from backup or superadmin when filling;
keep any real local value untouched unless force-overwrite.
Co-authored-by: Cursor <cursoragent@cursor.com>
Customer /api/get_settings dropped price_provider because SuperAdmin
catalog did not return it. Merge SA values when present; otherwise keep
the tenant copy so the app still receives the key.
Co-authored-by: Cursor <cursoragent@cursor.com>
Blank template values must not wipe local can_edit=0 settings like
price_provider until SuperAdmin actually saves a value for that tenant.
Co-authored-by: Cursor <cursoragent@cursor.com>
Force can_edit=1 for Montzar/price runtime keys via settings:deploy
and settings:sync-runtime-can-edit, so tenant DB stays correct even
when an older deploy SQL is still on the server.
Co-authored-by: Cursor <cursoragent@cursor.com>
editable_only now includes RUNTIME_KEYS; normalize can_edit in responses.
UpdateConfig and montzar login persist can_edit=1. SQL override moved before COMMIT.
Co-authored-by: Cursor <cursoragent@cursor.com>
Remove service_charge_percentage alias and config/fee.php fallback (empty → 0).
Move code-managed Montzar/price runtime keys to can_edit=1 in deploy SQL.
Add settings:deploy and deploy:tenant artisan commands for server deploy.
Advanced admin settings merge runtime keys from local DB; block manual edits.
Co-authored-by: Cursor <cursoragent@cursor.com>
Remove email/in-app paths and enforce sms action on create/update so
price alerts match the product requirement for SMS-only delivery.
Co-authored-by: Cursor <cursoragent@cursor.com>
Use double-quoted PHP string for Persian COMMENT; '' is SQL escaping, not valid inside PHP single quotes.
Co-authored-by: Cursor <cursoragent@cursor.com>
- New `show_in_list` column to control product visibility in customer list
- New `tv_price_formula_enabled` + `tv_price_formula` columns for separate TV pricing
- FormulaPriceService: isTvEnabled() and calculateTvForProduct()
- listTvProducts applies TV formula overrides before returning
- filterProductData handles both new field sets
Co-authored-by: Cursor <cursoragent@cursor.com>
Alerts now bind to a product_id and share one evaluator; displayed gold within a rounding step discharges the full wallet.
Co-authored-by: Cursor <cursoragent@cursor.com>