قیمت خرید
مخاطب: برنامهنویس نرمافزار حسابداری یا انبارداری که قیمت خرید کالاها را از فاکتور تامینکننده دارد و میخواهد آن را در سلر ۳۶۰ ثبت کند تا سود و زیان و ربات قیمتگذاری با قیمت درست کار کنند.
📖 مقدمه
Section titled “📖 مقدمه”سود هر فروش با قیمت خریدی حساب میشود که در روز همان فروش معتبر بوده است، نه با قیمت امروز. اگر قیمت خرید امروز بالا رفته باشد و سود فروشهای ماه گذشته با قیمت امروز حساب شود، همهی آن سودها اشتباه میشوند. به همین دلیل سلر ۳۶۰ قیمت خرید هر تنوع را به شکل بازهی تاریخ نگه میدارد؛ همان چیزی که در صفحهی «قیمت خرید» پنل با ستونهای «از تاریخ» و «تا تاریخ» میبینید.
با مسیرهای این صفحه میتوانید:
| کار | مسیر | در دسترس |
|---|---|---|
| خواندن بازههای قیمت خرید | GET /v1/purchase-prices |
فعال |
| ثبت قیمت خرید برای یک بازه | POST /v1/purchase-prices |
فعال |
| ویرایش یک بازه | PUT /v1/purchase-prices/{price_id} |
فعال |
| حذف یک بازه | DELETE /v1/purchase-prices/{price_id} |
فعال |
| تاریخچهی تغییر قیمتهای خرید | GET /v1/purchase-prices/changes |
فعال |
هیچکدام از این مسیرها چیزی در دیجیکالا نمینویسند؛ قیمت خرید فقط در سلر ۳۶۰ ثبت میشود.
⚙️ پیشنیازها
Section titled “⚙️ پیشنیازها”دسترسی (Scope)
Section titled “دسترسی (Scope)”| دسترسی | برچسب در پنل | برای |
|---|---|---|
purchasing:read |
«خواندن پیشنهاد خرید و سفارش خرید» | خواندن بازهها و تاریخچه |
purchasing:write |
«ثبت سفارش خرید» | ثبت، ویرایش و حذف بازه |
catalog:read |
«خواندن کاتالوگ کالا» | پیشنهاد میشود: برای یافتن variant_id هر کالا با کاتالوگ |
فعال بودن ماژول
Section titled “فعال بودن ماژول”ماژول «API و وبهوک» باید برای پنل فعال باشد؛ در غیر این صورت پاسخ 403 با خطای module_inactive برمیگردد. چون قیمت خرید فقط در سلر ۳۶۰ ثبت میشود، ثبت و ویرایش آن برای پنلی که اشتراک آن به پایان رسیده است هم ممکن است.
آدرس پایه
Section titled “آدرس پایه”https://api.seller360.ir🧮 مدل قیمت خرید
Section titled “🧮 مدل قیمت خرید”فیلدهای یک بازه (PurchasePrice)
Section titled “فیلدهای یک بازه (PurchasePrice)”| فیلد | برچسب در پنل | معنی |
|---|---|---|
id |
— | شناسهی بازه؛ برای ویرایش و حذف. |
variant_id |
«کد DKPC» | تنوعی که این قیمت برای آن است. |
cost |
«قیمت خرید» | قیمت خرید هر واحد، به ریال. |
valid_from |
«از تاریخ» | اولین روز اعتبار، شامل همان روز. |
valid_to |
«تا تاریخ» | آخرین روز اعتبار، شامل همان روز؛ null یعنی بازه باز است. |
source |
— | منبع ثبت: manual «دستی»، xlsx «فایل اکسل»، fx «قیمت ارزی» یا api. |
note |
— | یادداشت، مثلا شمارهی فاکتور تامینکننده. |
created_at |
«زمان ثبت» | زمان ثبت این بازه. |
بازهی باز و بازهی بسته
Section titled “بازهی باز و بازهی بسته”- بازهی بسته (
valid_toدارد): قیمت دقیقا ازvalid_fromتاvalid_toمعتبر است. - بازهی باز (
valid_toبرابرnull): قیمت تا روز پیش از شروع بازهی بعدی ادامه دارد، و اگر بازهی بعدی نباشد، تا همیشه. - روز بدون قیمت: روزی که هیچ بازهای آن را پوشش ندهد قیمت خرید ندارد؛ سود فروشهای آن روز حساب نمیشود و در پنل با «بازهی قرمز» نشان داده میشود.
یک مثال: بازهی تازه روی بازهی باز
Section titled “یک مثال: بازهی تازه روی بازهی باز”تنوع 84780448 از ۱ مهر ۱۴۰۵ (2026-09-23) یک بازهی باز با قیمت ۱۷٬۵۰۰٬۰۰۰ ریال دارد. فاکتوری میرسد که میگوید کالای ۱ تا ۱۰ آبان (2026-10-23 تا 2026-11-01) با ۱۸٬۵۰۰٬۰۰۰ ریال خریده شده است. پس از POST:
| بازه | valid_from |
valid_to |
cost |
|---|---|---|---|
| تکهی اول بازهی قبلی | 2026-09-23 |
2026-10-22 |
17500000 |
| بازهی تازه | 2026-10-23 |
2026-11-01 |
18500000 |
| تکهی دوم بازهی قبلی (باز) | 2026-11-02 |
null |
17500000 |
بازهی قبلی دو تکه شد تا هیچ دو قیمتی یک روز را پوشش ندهند. هر سه تغییر با یک شناسهی batch مشترک در تاریخچه ثبت میشوند.
فیلدهای تاریخچه (PurchasePriceChange)
Section titled “فیلدهای تاریخچه (PurchasePriceChange)”| فیلد | معنی |
|---|---|
id |
شناسهی تغییر. |
variant_id |
تنوع. |
price_id |
بازهی تغییرکرده؛ پس از حذف بازه هم باقی میماند. |
action |
create ثبت، update ویرایش یا delete حذف. |
before، after |
وضعیت بازه پیش و پس از تغییر (cost، valid_from، valid_to)؛ برای ثبت before و برای حذف after خالی است. |
batch |
تغییرهای یک ذخیره شناسهی مشترک دارند. |
reason |
page (صفحههای قیمت خرید پنل)، record (فایل قیمت یا جدول محصولات) یا api. |
created_at |
زمان تغییر. |
🔢 تازگی و اثر
Section titled “🔢 تازگی و اثر”- فوری: هر ثبت، ویرایش یا حذف در همان پاسخ دیده میشود و سود و زیان روزهای تغییرکرده از همان لحظه با قیمت تازه محاسبه میشود.
- ربات قیمتگذاری: اگر بازهی تغییرکرده امروز را پوشش دهد، قیمت خرید امروز تنوع که ربات قیمتگذاری میخواند هم در همان لحظه بهروز میشود.
- تاریخچه: هر تغییری که بازهای را بسازد، جابهجا کند یا حذف کند، یک ردیف در
GET /v1/purchase-prices/changesدارد؛ پس هر تغییر سود قابل توضیح است.
⚠️ هشدارها
Section titled “⚠️ هشدارها”📡 مسیرها
Section titled “📡 مسیرها”GET /v1/purchase-prices — بازههای قیمت خرید فعال
Section titled “GET /v1/purchase-prices — بازههای قیمت خرید ”بازهها، تازهترین شروع اول.
GET /v1/purchase-prices?variant_id=84780448&date=2026-10-28 HTTP/1.1Host: api.seller360.irAuthorization: Bearer s360_live_...پارامترها
| پارامتر | نوع | اجباری | توضیح |
|---|---|---|---|
page، size |
عدد | خیر | صفحهبندی؛ پیشفرض ۵۰، بیشینه ۵۰۰. |
variant_id |
عدد | خیر | فقط بازههای این تنوع. |
date |
تاریخ | خیر | فقط بازههایی که این روز را پوشش میدهند؛ یعنی قیمت معتبر در آن روز. |
پاسخ نمونه
{ "status": "ok", "data": [ { "id": 9082, "variant_id": 84780448, "cost": 18500000, "valid_from": "2026-10-23", "valid_to": "2026-11-01", "source": "api", "note": "فاکتور ۴۸۲ تامینکننده", "created_at": "2026-11-13T10:42:18+03:30" } ], "pager": { "page": 1, "item_per_page": 50, "total_pages": 1, "total_rows": 1 }}POST /v1/purchase-prices — ثبت قیمت برای یک بازه فعال
Section titled “POST /v1/purchase-prices — ثبت قیمت برای یک بازه ”بازهی تازه را روی بازههای فعلی تنوع مینویسد (هشدار ۱).
POST /v1/purchase-prices HTTP/1.1Host: api.seller360.irAuthorization: Bearer s360_live_...Idempotency-Key: inv-482-84780448Content-Type: application/json
{ "variant_id": 84780448, "cost": 18500000, "valid_from": "2026-10-23", "valid_to": "2026-11-01", "note": "فاکتور ۴۸۲ تامینکننده"}| فیلد بدنه | نوع | اجباری | توضیح |
|---|---|---|---|
variant_id |
عدد | بله | تنوع. |
cost |
عدد | بله | قیمت خرید هر واحد به ریال؛ صفر یا بیشتر. |
valid_from |
تاریخ | بله | اولین روز؛ نمیتواند بعد از امروز باشد. |
valid_to |
تاریخ یا null |
خیر | آخرین روز، شامل همان روز؛ نفرستید یا null بفرستید تا بازه باز بماند. |
note |
متن | خیر | تا ۲۰۰ نویسه. |
پاسخ نمونه (کد 201): همهی بازههای تنوع پس از ثبت.
{ "status": "ok", "data": [ { "id": 9083, "variant_id": 84780448, "cost": 17500000, "valid_from": "2026-11-02", "valid_to": null, "source": "manual", "note": null, "created_at": "2026-11-13T10:42:18+03:30" }, { "id": 9082, "variant_id": 84780448, "cost": 18500000, "valid_from": "2026-10-23", "valid_to": "2026-11-01", "source": "api", "note": "فاکتور ۴۸۲ تامینکننده", "created_at": "2026-11-13T10:42:18+03:30" }, { "id": 8510, "variant_id": 84780448, "cost": 17500000, "valid_from": "2026-09-23", "valid_to": "2026-10-22", "source": "manual", "note": null, "created_at": "2026-09-23T11:05:40+03:30" } ]}خطاهای این مسیر
| کد HTTP | خطا | معنی | تکرار بیخطر است؟ |
|---|---|---|---|
400 |
invalid_parameter |
فیلدی نادرست است یا جا افتاده است. | خیر؛ بدنه را اصلاح کنید. |
404 |
variant_not_found |
این تنوع در این پنل نیست. | خیر. |
422 |
purchase_price_range_invalid |
شروع بعد از امروز یا بعد از پایان است. | خیر؛ تاریخها را اصلاح کنید. |
409 |
idempotency_mismatch |
این کلید یکتا قبلا با بدنهی دیگری استفاده شده است. | خیر؛ کلید تازه بسازید. |
409 |
idempotency_in_progress |
درخواستی با همین کلید در حال انجام است. | بله، چند ثانیه بعد. |
PUT /v1/purchase-prices/{price_id} — ویرایش یک بازه فعال
Section titled “PUT /v1/purchase-prices/{price_id} — ویرایش یک بازه ”همان قواعد ثبت؛ بازههای همسایه در صورت همپوشانی کوتاه یا حذف میشوند. همهی فیلدهای بازه را بفرستید.
| فیلد بدنه | نوع | اجباری | توضیح |
|---|---|---|---|
cost |
عدد | بله | ریال. |
valid_from |
تاریخ | بله | نمیتواند بعد از امروز باشد. |
valid_to |
تاریخ یا null |
خیر | خالی یعنی باز. |
note |
متن | خیر | تا ۲۰۰ نویسه. |
پاسخ موفق: کد 200 با همهی بازههای تنوع. خطاها همان خطاهای ثبتاند؛ اگر بازه وجود نداشته باشد، کد 404 و خطای not_found برمیگردد.
DELETE /v1/purchase-prices/{price_id} — حذف یک بازه فعال
Section titled “DELETE /v1/purchase-prices/{price_id} — حذف یک بازه ”پاسخ موفق: کد 200 با بازههای باقیماندهی تنوع (هشدار ۴).
GET /v1/purchase-prices/changes — تاریخچهی تغییرها فعال
Section titled “GET /v1/purchase-prices/changes — تاریخچهی تغییرها ”هر ثبت، ویرایش یا حذف، تازهترین اول.
| پارامتر | نوع | اجباری | توضیح |
|---|---|---|---|
variant_id |
عدد | خیر | فقط تغییرهای این تنوع. |
page، size |
عدد | خیر | صفحهبندی. |
{ "status": "ok", "data": [ { "id": 30212, "variant_id": 84780448, "price_id": 8510, "action": "update", "before": { "cost": 17500000, "valid_from": "2026-09-23", "valid_to": null }, "after": { "cost": 17500000, "valid_from": "2026-09-23", "valid_to": "2026-10-22" }, "batch": "a91c0e2f4b7d", "reason": "api", "created_at": "2026-11-13T10:42:18+03:30" }, { "id": 30211, "variant_id": 84780448, "price_id": 9082, "action": "create", "before": null, "after": { "cost": 18500000, "valid_from": "2026-10-23", "valid_to": "2026-11-01" }, "batch": "a91c0e2f4b7d", "reason": "api", "created_at": "2026-11-13T10:42:18+03:30" } ], "pager": { "page": 1, "item_per_page": 50, "total_pages": 1, "total_rows": 3 }}🔔 رویدادهای وبهوک
Section titled “🔔 رویدادهای وبهوک”این بخش رویداد وبهوک جداگانه ندارد؛ هر تغییر قیمت خرید با پاسخ همان درخواست و در تاریخچه دیده میشود. فهرست همهی رویدادها در وبهوکها آمده است.
💻 نمونهکد: ثبت قیمت خرید یک فاکتور
Section titled “💻 نمونهکد: ثبت قیمت خرید یک فاکتور”- برای هر قلم فاکتور،
variant_idرا باGET /v1/variants?sku=...پیدا کنید. - بازه را با
POST /v1/purchase-pricesثبت کنید؛ کلید یکتا را از شمارهی فاکتور و تنوع بسازید. - بازههای برگشتی در پاسخ را جایگزین نسخهی ذخیرهشدهی خود کنید.
curl -X POST https://api.seller360.ir/v1/purchase-prices \ -H "Authorization: Bearer $S360_API_KEY" \ -H "Idempotency-Key: inv-482-84780448" \ -H "Content-Type: application/json" \ -d '{"variant_id": 84780448, "cost": 18500000, "valid_from": "2026-10-23", "valid_to": "2026-11-01", "note": "INV-482"}'$ch = curl_init("https://api.seller360.ir/v1/purchase-prices");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer " . getenv("S360_API_KEY"), "Idempotency-Key: inv-482-84780448", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "variant_id" => 84780448, "cost" => 18500000, "valid_from" => "2026-10-23", "valid_to" => "2026-11-01", "note" => "INV-482", ]), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 20,]);$res = json_decode(curl_exec($ch), true);if (($res["error"]["code"] ?? null) === "purchase_price_range_invalid") { // تاریخ شروع بعد از امروز یا بعد از پایان است}import os, requests
res = requests.post( "https://api.seller360.ir/v1/purchase-prices", headers={ "Authorization": f"Bearer {os.environ['S360_API_KEY']}", "Idempotency-Key": "inv-482-84780448", }, json={"variant_id": 84780448, "cost": 18500000, "valid_from": "2026-10-23", "valid_to": "2026-11-01", "note": "INV-482"}, timeout=20,).json()if res["status"] == "ok": ranges = res["data"] # همهی بازههای تنوع پس از ثبتconst res = await fetch('https://api.seller360.ir/v1/purchase-prices', { method: 'POST', headers: { Authorization: `Bearer ${process.env.S360_API_KEY}`, 'Idempotency-Key': 'inv-482-84780448', 'Content-Type': 'application/json', }, body: JSON.stringify({ variant_id: 84780448, cost: 18500000, valid_from: '2026-10-23', valid_to: '2026-11-01', note: 'INV-482', }),})const body = await res.json()if (body.status === 'ok') { const ranges = body.data // همهی بازههای تنوع پس از ثبت}using var http = new HttpClient();var req = new HttpRequestMessage(HttpMethod.Post, "https://api.seller360.ir/v1/purchase-prices");req.Headers.Add("Authorization", $"Bearer {Environment.GetEnvironmentVariable("S360_API_KEY")}");req.Headers.Add("Idempotency-Key", "inv-482-84780448");req.Content = JsonContent.Create(new { variant_id = 84780448, cost = 18500000, valid_from = "2026-10-23", valid_to = "2026-11-01", note = "INV-482",});var res = await http.SendAsync(req);var body = await res.Content.ReadFromJsonAsync<JsonElement>();