| | | 1 | | namespace Services.ApiServices.BergApi; |
| | | 2 | | |
| | | 3 | | /// <summary>Тип отгрузки Berg (<c>order[dispatch_type]</c>).</summary> |
| | | 4 | | public static class BergDispatchType |
| | | 5 | | { |
| | | 6 | | public const int SelfPickup = 2; |
| | | 7 | | public const int Delivery = 3; |
| | | 8 | | public const int RushDelivery = 60580; |
| | | 9 | | } |
| | | 10 | | |
| | | 11 | | /// <summary>Время отгрузки Berg (<c>order[dispatch_time]</c>).</summary> |
| | | 12 | | public static class BergDispatchTime |
| | | 13 | | { |
| | | 14 | | /// <summary>До 15:00.</summary> |
| | | 15 | | public const int BeforeMidday = 1; |
| | | 16 | | |
| | | 17 | | /// <summary>После 15:00.</summary> |
| | | 18 | | public const int AfterMidday = 2; |
| | | 19 | | } |
| | | 20 | | |
| | | 21 | | /// <summary>Тип оплаты Berg (<c>order[payment_type]</c>).</summary> |
| | | 22 | | public static class BergPaymentType |
| | | 23 | | { |
| | | 24 | | public const int Cash = 1; |
| | | 25 | | public const int Cashless = 2; |
| | | 26 | | } |
| | | 27 | | |
| | | 28 | | /// <summary> |
| | | 29 | | /// Строка заказа Berg. Предложение идентифицируется парой resource_id + warehouse_id: |
| | | 30 | | /// отдельного идентификатора оффера <c>ordering/get_stock.json</c> не отдаёт. |
| | | 31 | | /// </summary> |
| | | 32 | | public sealed record BergOrderItemRequest( |
| | | 33 | | long ResourceId, |
| | | 34 | | long WarehouseId, |
| | | 35 | | decimal Quantity, |
| | | 36 | | decimal? MaxPrice = null, |
| | | 37 | | int? DeliveryType = null, |
| | | 38 | | bool? IsTransit = null, |
| | | 39 | | string? Comment = null); |
| | | 40 | | |
| | | 41 | | /// <summary>Заказ Berg для <c>ordering/place_order.json</c>.</summary> |
| | | 42 | | public sealed record BergOrderRequest |
| | | 43 | | { |
| | | 44 | | public required IReadOnlyList<BergOrderItemRequest> Items { get; init; } |
| | | 45 | | |
| | | 46 | | /// <summary>Тип отгрузки. Обязателен.</summary> |
| | | 47 | | public int DispatchType { get; init; } = BergDispatchType.Delivery; |
| | | 48 | | |
| | | 49 | | /// <summary>Дата отгрузки. Обязательна, передаётся как ГГГГ-ММ-ДД.</summary> |
| | | 50 | | public required DateTime DispatchAt { get; init; } |
| | | 51 | | |
| | | 52 | | /// <summary>Время отгрузки. Обязательно.</summary> |
| | | 53 | | public int DispatchTime { get; init; } = BergDispatchTime.BeforeMidday; |
| | | 54 | | |
| | | 55 | | /// <summary>Адрес из справочника. Berg принимает его только с доставкой (dispatch_type = 3).</summary> |
| | | 56 | | public long? ShipmentAddressId { get; init; } |
| | | 57 | | |
| | | 58 | | public int? PaymentType { get; init; } |
| | | 59 | | |
| | | 60 | | public string? Person { get; init; } |
| | | 61 | | |
| | | 62 | | public string? Phone { get; init; } |
| | | 63 | | |
| | | 64 | | public string? Comment { get; init; } |
| | | 65 | | |
| | | 66 | | /// <summary> |
| | | 67 | | /// Уникальный числовой идентификатор заказа на стороне клиента. Berg отклоняет повтор |
| | | 68 | | /// (<c>ERR_ORDER_REFERENCE_NOT_UNIQUE</c>), поэтому это наша защита от двойного оформления. |
| | | 69 | | /// </summary> |
| | | 70 | | public long? Reference { get; init; } |
| | | 71 | | |
| | | 72 | | /// <summary>Заказ сохраняется в истории Berg, но не обрабатывается — режим проверки.</summary> |
| | | 73 | | public bool IsTest { get; init; } |
| | | 74 | | |
| | | 75 | | /// <summary> |
| | | 76 | | /// Разрешает разместить заказ, даже если часть строк не проходит по остатку, кратности |
| | | 77 | | /// или максимальной цене: такие строки Berg пропускает и возвращает в warnings. |
| | | 78 | | /// </summary> |
| | | 79 | | public bool Force { get; init; } |
| | | 80 | | } |
| | | 81 | | |
| | | 82 | | /// <summary>Строка ответа Berg на размещение заказа или на запрос статусов.</summary> |
| | | 83 | | public sealed record BergOrderItemState( |
| | | 84 | | int Sequence, |
| | | 85 | | long? ResourceId, |
| | | 86 | | string? Article, |
| | | 87 | | string? Brand, |
| | | 88 | | string? Name, |
| | | 89 | | long? WarehouseId, |
| | | 90 | | string? WarehouseName, |
| | | 91 | | decimal? Quantity, |
| | | 92 | | decimal? Price, |
| | | 93 | | int? StateId, |
| | | 94 | | string? StateName, |
| | | 95 | | int? StateType, |
| | | 96 | | DateTime? AverageTime, |
| | | 97 | | DateTime? AssuredTime, |
| | | 98 | | string? Comment); |
| | | 99 | | |
| | | 100 | | /// <summary>Заказ Berg, как его отдают place_order и ordering/states.</summary> |
| | 24 | 101 | | public sealed record BergOrderState( |
| | 57 | 102 | | long Id, |
| | 3 | 103 | | long? Reference, |
| | 4 | 104 | | bool IsTest, |
| | 2 | 105 | | int? DispatchType, |
| | 2 | 106 | | DateTime? DispatchAt, |
| | 2 | 107 | | int? DispatchTime, |
| | 4 | 108 | | int? PaymentType, |
| | 4 | 109 | | string? ShipmentAddress, |
| | 3 | 110 | | long? ShipmentAddressId, |
| | 2 | 111 | | string? Person, |
| | 2 | 112 | | string? Phone, |
| | 2 | 113 | | string? Comment, |
| | 2 | 114 | | DateTime? CreatedAt, |
| | 53 | 115 | | IReadOnlyList<BergOrderItemState> Items); |
| | | 116 | | |
| | | 117 | | /// <summary>Ошибка или предупреждение Berg: код и текст.</summary> |
| | | 118 | | public sealed record BergMessage(string Code, string Text); |
| | | 119 | | |
| | | 120 | | /// <summary> |
| | | 121 | | /// Результат размещения заказа. Berg может одновременно вернуть заказ и предупреждения |
| | | 122 | | /// (при <c>force=1</c> проблемные строки пропускаются, а остальные размещаются). |
| | | 123 | | /// </summary> |
| | | 124 | | public sealed record BergPlaceOrderResult( |
| | | 125 | | BergOrderState? Order, |
| | | 126 | | IReadOnlyList<BergMessage> Errors, |
| | | 127 | | IReadOnlyList<BergMessage> Warnings) |
| | | 128 | | { |
| | | 129 | | public bool IsSuccess => Order is not null && Errors.Count == 0; |
| | | 130 | | } |
| | | 131 | | |
| | | 132 | | /// <summary>Статус из справочника <c>references/states.json</c>.</summary> |
| | | 133 | | /// <param name="Type">0 — обычный, 1 — присваивается при размещении, 2 — завершающий.</param> |
| | | 134 | | public sealed record BergState(int Id, string Name, int Type) |
| | | 135 | | { |
| | | 136 | | /// <summary>Статусы этого типа Berg присваивает по завершении обработки заказа.</summary> |
| | | 137 | | public const int FinalType = 2; |
| | | 138 | | |
| | | 139 | | public bool IsFinal => Type == FinalType; |
| | | 140 | | } |